为 Python 3 urllib 开启调试输出
在Python 2中,你可以通过以下方式从urllib获取调试输出:
import httplib
import urllib
httplib.HTTPConnection.debuglevel = 1
response = urllib.urlopen('http://example.com').read()
但是在Python 3中,这个功能似乎被移到了:
http.client.HTTPConnection.set_debuglevel(level)
不过,我是直接使用urllib,而不是http.client。我该如何设置才能让我的HTTP请求以这种方式显示调试信息呢?
这是我目前使用的代码。如果我想获取调试信息,最好的方法是什么呢?
#Request Login page
cookiejar = http.cookiejar.CookieJar()
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cookiejar))
request = urllib.request.Request(options.uri)
add_std_headers(request)
response = opener.open(request)
response_string = response.read().decode("utf8")
# ...
3 个回答
今天的情况跟上次回答的时候有点不一样。
我默认的 urllib3
连接是通过 PoolManager
来处理的。
开启 debug level
的功能有点缺失,不过现在有一个很不错的 logger
使用方法。
https://urllib3.readthedocs.io/en/stable/user-guide.html#logging
日志级别的值从低到高分别是:
- DEBUG
- INFO
- WARNING
- ERROR
- CRITICAL
下面这行代码可以让你开始把调试信息输出到标准输出(stdout):
import logging
logging.basicConfig(format='%(asctime)s - %(message)s', level=logging.DEBUG)
logging.getLogger("urllib3").setLevel(logging.DEBUG)
这样你会得到类似这样的输出:
2023-02-01 21:02:24,221 - Resetting dropped connection: localhost
2023-02-01 21:02:24,227 - http://localhost:9000 "GET /web/path HTTP/1.1" 200 100
对于那些最近看到这个问题的人(大约从2016年5月开始),虽然之前的答案在某个时候可能是正确的,但从Python 3.5.2版本开始,http.client.HTTPConnection.debuglevel
这个设置完全被忽略了,取而代之的是urllib.request.HTTPHandler
的构造函数参数debuglevel
。
这是因为这个改动,它将http.client.HTTPConnection.debuglevel
的值设置为urllib.request.HTTPHandler
构造函数参数debuglevel
中所设置的值,具体在这一行。
有一个拉取请求已经被提出以修复这个问题,但在此之前,你可以通过修改HTTPHandler
和HTTPSHandler
的__init__
方法来让它们尊重全局值,方法如下:
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 = 1
就可以在整个应用程序中开启HTTP调试功能。urllib.request
还是会使用 http.client
。
似乎还有一种方法可以为单个处理器设置调试级别(通过创建 urllib.request.HTTPHandler(debuglevel=1)
并用它来构建一个打开器),但在我安装的Python3(3.0b3)中,这个功能实际上并没有实现。我想在更新的版本中这个问题可能已经解决了!