urllib opener 하나만 직접 연결해야 한다면 ProxyHandler에 빈 매핑을 전달하세요.

from urllib.request import ProxyHandler, build_opener

direct = build_opener(ProxyHandler({}))

with direct.open("https://example.com/", timeout=10) as response:
    print(response.status)

빈 딕셔너리는 프록시 경로를 제공하지 않습니다. 반면 매핑을 생략하면 핸들러가 환경과 플랫폼 설정에서 프록시를 찾습니다. 이 두 생성 방식은 서로 다른 정책을 나타냅니다.

예제는 Python 표준 라이브러리를 사용하며 정상적인 HTTPS 검증을 유지합니다. with 블록은 응답을 닫으며, 예외 때문에 블록을 빠져나가는 경우에도 마찬가지입니다.

한 애플리케이션에서 직접 요청과 프록시 요청 함께 사용하기

opener 두 개가 각 정책을 맡으면 호출 사이에 환경 변수를 바꿀 필요가 없습니다.

from urllib.request import ProxyHandler, build_opener

direct = build_opener(ProxyHandler({}))
proxied = build_opener(ProxyHandler({
    "http": "http://127.0.0.1:8080",
    "https": "http://127.0.0.1:8080",
}))

with proxied.open("https://example.com/", timeout=10) as response:
    print(response.status)

루프백 주소를 자신의 HTTP 프록시로 바꾸거나, 프록시 연결 비교용 후보를 HTTP 프록시 목록에서 선택하세요. 서비스에서 허용하면 HTTPS 대상 연결을 CONNECT를 통해 전달할 수 있습니다. 수신 측의 프로토콜과 인증 지원이 핸들러와 맞아야 합니다.

기본 opener 유지하기

해당 경로를 담당하는 객체를 통해 direct.open이나 proxied.open을 호출하세요. install_opener는 urllib의 편의 함수들이 사용하는 프로세스 전체의 기본값을 바꾸므로, 라이브러리가 이를 사용하면 무관한 코드에도 영향을 줄 수 있습니다. 위의 독립된 opener에는 필요하지 않습니다.

timeout 인수는 개별 작업 설정이며 각 전송 전체의 실제 경과 시간 제한이 아닙니다. 작업에 필요한 데이터만 읽고, 엄격한 총시간 예산이 있다면 상위 수준의 마감 시간을 사용하세요.

이 opener 객체들은 다른 라이브러리의 클라이언트, 기존 프로세스 또는 브라우저의 프록시 설정을 변경하지 않습니다.

관련 글