python-3.x 详细记录urllib.request.urlopen

bf1o4zei  于 2022-11-19  发布在  Python
关注(0)|答案(1)|浏览(166)

有没有办法为urllib启用某种详细的日志记录?我特别想找出它使用的是哪个TLS-Cert文件,使用的是哪个代理。也就是说,它是否真的使用了我在env中配置的内容。

sg3maiej

sg3maiej1#

在Python 3.5.1及更早版本中,可以通过两种方式来实现:
1.您可以使用HTTPHandlerHTTPSHandler的构造函数参数(如SO答案所示):

import urllib.request

handler = urllib.request.HTTPHandler(debuglevel=10)
opener = urllib.request.build_opener(handler)
content = opener.open('http://example.com').read()

print(content[0:120])

1.您可以设置http.client.HTTPConnection.debuglevel类变量以启用所有未来连接的日志记录。

import urllib.request
import http.client

http.client.HTTPConnection.debuglevel = 1
content = urllib.request.urlopen('http://example.com').read()

print(content[0:120])

在Python 3.5.2及更高版本中,第二个方法不再起作用(第一个方法仍然可以正常工作)。要使用http.client.HTTPConnection.debuglevel类变量,你需要像这样对HTTPHandlerHTTPSHandler__init__方法进行monkey补丁(至少在this PR被合并并向后移植之前):

https_old_init = urllib.request.HTTPSHandler.__init__

def https_new_init(self, debuglevel=None, context=None, check_hostname=None):
    debuglevel = debuglevel if debuglevel is not None else http.client.HTTPSConnection.debuglevel
    https_old_init(self, debuglevel, context, check_hostname)

urllib.request.HTTPSHandler.__init__ = https_new_init

http_old_init = urllib.request.HTTPHandler.__init__

def http_new_init(self, debuglevel=None):
    debuglevel = debuglevel if debuglevel is not None else http.client.HTTPSConnection.debuglevel
    http_old_init(self, debuglevel)

urllib.request.HTTPHandler.__init__ = http_new_init

(* 注意:我不建议将HTTPHandler中的debuglevel设置为方法参数的默认值,因为方法参数的默认值是在函数定义求值时求值的,对于HTTPHandler的构造函数,这是在导入模块urllib.request时。*)
你必须这么做的原因(如果你想使用http.client.HTTPConnection.debuglevel类变量作为全局值)是因为Python 3.5.2开始引入的change,它设置了http.client.HTTPConnection.debuglevelinstance 变量(通常只隐藏相应的类变量)HTTPHandlerHTTPSHandler类上的debuglevel构造函数参数的值,而不管是否设置了该参数。因为它默认为0,示例变量HTTPConnection.debuglevel将始终被传递给构造函数的值或默认值0覆盖。

相关问题