Python HTTP请求和调试级别日志记录到日志文件
我很难在HTTP请求的日志文件中获取调试级别的日志,比如控制台中的日志,比如:Python HTTP请求和调试级别日志记录到日志文件,python,python-3.x,logging,Python,Python 3.x,Logging,我很难在HTTP请求的日志文件中获取调试级别的日志,比如控制台中的日志,比如: DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): URI:443 DEBUG:urllib3.connectionpool:URL:443 "POST /endpoint HTTP/1.1" 200 None 有关以下代码: import logging from logging.handlers import TimedRotating
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): URI:443
DEBUG:urllib3.connectionpool:URL:443 "POST /endpoint HTTP/1.1" 200 None
有关以下代码:
import logging
from logging.handlers import TimedRotatingFileHandler
_logger = logging.getLogger(__name__)
def setup_logging(loglevel):
logFormatter = logging.Formatter("%(asctime)s [%(threadName)-12.12s] [%(levelname)-5.5s] %(message)s")
if loglevel is not None:
if loglevel == 10:
http.client.HTTPConnection.debuglevel = 1
logformat = "%(asctime)s [%(threadName)-12.12s] [%(levelname)-5.5s] %(message)s"
logging.basicConfig(level=loglevel, stream=sys.stdout, format=logformat, datefmt="%Y-%m-%d %H:%M:%S")
fileHandler = logging.handlers.TimedRotatingFileHandler("{0}/{1}.log".format(logPath, logFileName), when="midnight")
fileHandler.setFormatter(logFormatter)
_logger.setLevel(logging.DEBUG)
_logger.addHandler(fileHandler)
当我用logging.DEBUG调用它时,日志文件将只包含我在代码中指定为_logger.info或_logger.DEBUG的内容,与控制台日志输出没有类似之处
附言。
示例代码如何称呼它:
def main(args):
args = parse_args(args)
cfg = config(args.env)
setup_logging(logging.DEBUG, cfg)
requests.get("https://stackoverflow.com/a/58769712/100297")
您在错误的位置添加处理程序和级别更改 Python日志模块根据日志对象的名称和日志对象的存在,将日志对象视为存在于层次结构中。这些名称中的分隔符。记录器的名称foo.bar.baz在逻辑上被放置为foo.bar和foo的子级(如果存在)。层次结构的基础是根记录器,它没有名称。您可以使用logging.getLogger访问它,但是没有参数,也没有参数可以工作 现在,在记录消息时,首先消息必须通过记录器的有效级别。如果它们传递消息,则消息将从当前记录器传递到根目录下的每个记录器上的处理程序,前提是它们清除找到的每个处理程序的级别 为了找到有效级别,遍历层次结构以找到具有级别集的最近记录器对象;如果没有,则消息总是传递。当遍历层次结构以查找处理程序时,如果将日志对象设置为False,则遍历将停止 当您试图处理urllib3.connectionpool的消息时,需要在以下三个位置之一放置处理程序:urllib3.connectionpool的记录器、urllib3的记录器或根记录器。你的代码不能做到这一点 而是在自己的记录器上使用不同的名称设置处理程序:
_logger = logging.getLogger(__name__)
保证与根记录器不匹配的名称必须为空,urllib3或urllib3.connectionpool记录器也不能为空,这意味着您的模块也称为urllib3或urllib3.connectionpool
因为它不在urllib3.connectionpool日志消息将遵循的路径中,所以您的处理程序永远不会得到这些消息
相反,您希望配置根记录器:
您可以将每个处理程序的日志级别设置为希望在该处理程序上看到的日志级别,而不是在根记录器上或根记录器之外。请记住,根记录器上设置的级别用于确定层次结构中没有直接设置级别的其他记录器的有效级别,并且有效级别用作所有消息的“高水位线”。如果根记录器设置为INFO,并且没有配置其他处理程序,则处理程序将永远不会看到调试消息。根记录器的默认级别为警告
通常,您只希望在模块中使用命名的记录器来生成日志消息,并将所有处理程序放在根上。其他任何内容都是专门的,“高级”使用记录器模块,例如,仅用于urllib3日志消息的专用、单独的处理程序,或者通过将其最低级别的记录器对象设置为PROPAGE=False来使整个包静音
最后,logging.basicConfig也配置根记录器,但前提是根记录器上没有处理程序。如果使用force=True,则basicConfig将删除所有现有处理程序,然后在根目录上配置处理程序。它将始终创建一个格式化程序实例,并在所有处理程序上设置它
您可以使用basicConfig满足所有根记录器需求:
import http.client
import logging
import os.path
import sys
from logging.handlers import TimedRotatingFileHandler
def setup_logging(loglevel):
# the file handler receives all messages from level DEBUG on up, regardless
fileHandler = TimedRotatingFileHandler(
os.path.join(logPath, logFileName + ".log"),
when="midnight"
)
fileHandler.setLevel(logging.DEBUG)
handlers = [fileHandler]
if loglevel is not None:
# if a log level is configured, use that for logging to the console
stream_handler = logging.StreamHandler(sys.stdout)
stream_handler.setLevel(loglevel)
handlers.append(stream_handler)
if loglevel == logging.DEBUG:
# when logging at debug level, make http.client extra chatty too
# http.client *uses `print()` calls*, not logging.
http.client.HTTPConnection.debuglevel = 1
# finally, configure the root logger with our choice of handlers
# the logging level of the root set to DEBUG (defaults to WARNING otherwise).
logformat = "%(asctime)s [%(threadName)-12.12s] [%(levelname)-5.5s] %(message)s"
logging.basicConfig(
format=logformat, datefmt="%Y-%m-%d %H:%M:%S",
handlers=handlers, level=logging.DEBUG
)
旁注:http.client库不使用日志来输出调试消息;它将始终使用“打印”来输出这些内容。如果您想在日志中看到这些消息,则需要对库进行修补,添加一个可选的全局打印:
应用了上面的http.client技巧和setup_loggingloging.DEBUG后,我看到以下日志在stdout上和使用请求时出现在文件中。gethttps://stackoverflow.com/a/58769712/100297:
2019-11-08 16:17:26[主线程][调试]启动新的HTTPS连接1:stackoverflow.com:443
2019-11-08 16:17:27[主线程][调试]发送:b'GET/a/58769712/100297 HTTP/1.1\r\n主机:stackoverflow.com\r\n用户代理:python请求/2.22.0\r\n接受编码:gzip,deflate\r\n接受:/*\r\n连接:保持活动\r\n\r\n
2019-11-08 16:17:27[MainThread][DEBUG]答复:“找到HTTP/1.1 302\r\n”
2019-11-08 16:17:27[主线程][调试]头:缓存控制:专用
2019-11-08 16:17:27[MainThread][DEBUG]头:内容类型:text/html;字符集=utf-8
2019-11-08 16:17:27[主线程][调试]标题:位置:/questions/58738195/python http请求和调试级别日志记录到日志文件/5876971258769712
2019-11-08 16:17:27[主线程][调试]标题:X-Frame-Options:SAMEORIGIN
2019-11-08 16:17:27[主线程][调试]标题:X-Request-Guid:761bd2f8-3e5c-453a-ab46-d01284940541
2019-11-08 16:17:27[主线][DE
错误]标题:严格的传输安全性:最大年龄=15552000
2019-11-08 16:17:27[主线程][调试]标题:功能策略:麦克风“无”;发言者“无”
2019-11-08 16:17:27[主线程][调试]头:内容安全策略:升级不安全的请求;框住祖先的自我https://stackexchange.com
2019-11-08 16:17:27[主线程][调试]头:接受范围:字节
2019-11-08 16:17:27[主线程][调试]头:年龄:0
2019-11-08 16:17:27[主线程][调试]标题:内容长度:214
2019-11-08 16:17:27[主线程][调试]头:接受范围:字节
2019-11-08 16:17:27[主线程][调试]标题:日期:2019年11月8日星期五16:17:27 GMT
2019-11-08 16:17:27[主线程][调试]头:通孔:1.1
2019-11-08 16:17:27[主线程][调试]头:年龄:0
2019-11-08 16:17:27[主线程][调试]头:连接:保持活动状态
2019-11-08 16:17:27[主线程][调试]头:X服务方:cache-lhr7324-LHR
2019-11-08 16:17:27[主线程][调试]头:X缓存:未命中
2019-11-08 16:17:27[主线程][调试]头:X-Cache-Hits:0
2019-11-08 16:17:27[主线程][调试]头:X定时器:S1573229847.069848,VS0,VE80
2019-11-08 16:17:27[主线程][调试]头:变化:快速SSL
2019-11-08 16:17:27[主线程][调试]头:X-DNS-Prefetch-Control:关闭
2019-11-08 16:17:27[主线程][调试]头:设置Cookie:prov=0e92634f-abce-9f8e-1865-0D35EBEC595;domain=.stackoverflow.com;expires=周五,2055年1月1日00:00:00 GMT;路径=/;HttpOnly
2019-11-08 16:17:27[主线程][调试]https://stackoverflow.com:443 GET/a/58769712/100297 HTTP/1.1 302 214
2019-11-08 16:17:27[MainThread][DEBUG]发送:b'GET/questions/58738195/python http请求和调试级别日志到日志文件/58769712 http/1.1\r\nHost:stackoverflow.com\r\n用户代理:python请求/2.22.0\r\n接受编码:gzip,放气\r\n接受:*/*\r\n连接:保持活动\r\n检查:prov=0e92634f-abce-9f8e-1865-0d35ebecc595\r\n\r\n
2019-11-08 16:17:27[MainThread][DEBUG]回复:“HTTP/1.1200正常\r\n”
2019-11-08 16:17:27[主线程][调试]头:缓存控制:专用
2019-11-08 16:17:27[MainThread][DEBUG]头:内容类型:text/html;字符集=utf-8
2019-11-08 16:17:27[MainThread][DEBUG]头:内容编码:gzip
2019-11-08 16:17:27[主线程][调试]标题:上次修改:2019年11月8日星期五16:16:07 GMT
2019-11-08 16:17:27[主线程][调试]标题:X-Frame-Options:SAMEORIGIN
2019-11-08 16:17:27[主线程][调试]标题:X-Request-Guid:5e48399e-a91c-44aa-aad6-00a96014131f
2019-11-08 16:17:27[主线程][调试]头:严格的传输安全性:最大年龄=15552000
2019-11-08 16:17:27[主线程][调试]标题:功能策略:麦克风“无”;发言者“无”
2019-11-08 16:17:27[主线程][调试]头:内容安全策略:升级不安全的请求;框住祖先的自我https://stackexchange.com
2019-11-08 16:17:27[主线程][调试]头:接受范围:字节
2019-11-08 16:17:27[主线程][调试]头:年龄:0
2019-11-08 16:17:27[主线程][调试]标题:内容长度:42625
2019-11-08 16:17:27[主线程][调试]头:接受范围:字节
2019-11-08 16:17:27[主线程][调试]标题:日期:2019年11月8日星期五16:17:27 GMT
2019-11-08 16:17:27[主线程][调试]头:通孔:1.1
2019-11-08 16:17:27[主线程][调试]头:年龄:0
2019-11-08 16:17:27[主线程][调试]头:连接:保持活动状态
2019-11-08 16:17:27[主线程][调试]头:X服务方:cache-lhr7324-LHR
2019-11-08 16:17:27[主线程][调试]头:X缓存:未命中
2019-11-08 16:17:27[主线程][调试]头:X-Cache-Hits:0
2019-11-08 16:17:27[主线程][调试]头:X定时器:S1573229847.189349,VS0,VE95
2019-11-08 16:17:27[MainThread][DEBUG]头:变化:接受编码,快速SSL
2019-11-08 16:17:27[主线程][调试]头:X-DNS-Prefetch-Control:关闭
2019-11-08 16:17:27[主线程][调试]https://stackoverflow.com:443 GET/questions/58738195/python http请求和调试级别日志记录到日志文件/58769712 http/1.1 200 42625
您可以使用以下文件复制此文件:
import requests
import sys
logPath, logFileName = "/tmp", "demo"
level = logging.DEBUG if "-v" in sys.argv else None
setup_logging(level)
requests.get("https://stackoverflow.com/a/58769712/100297")
除了上述代码之外,还添加了。
_logger = logging.getLogger(__name__)
保证与根记录器不匹配的名称必须为空,urllib3或urllib3.connectionpool记录器也不能为空,这意味着您的模块也称为urllib3或urllib3.connectionpool
因为它不在urllib3.connectionpool日志消息将遵循的路径中,所以您的处理程序永远不会得到这些消息
相反,您希望配置根记录器:
您可以将每个处理程序的日志级别设置为希望在该处理程序上看到的日志级别,而不是在根记录器上或根记录器之外。请记住,根记录器上设置的级别用于确定层次结构中没有直接设置级别的其他记录器的有效级别,并且有效级别用作所有消息的“高水位线”。如果根记录器设置为INFO,并且没有配置其他处理程序,则处理程序将永远不会看到调试消息。根记录器的默认级别为警告
通常,您只希望在模块中使用命名的记录器来生成日志消息,并将所有处理程序放在根上。其他任何内容都是专门的,“高级”使用记录器模块,例如,仅用于urllib3日志消息的专用、单独的处理程序,或者通过将其最低级别的记录器对象设置为PROPAGE=False来使整个包静音
最后,logging.basicConfig也配置根记录器,但前提是根记录器上没有处理程序。如果使用force=True,则basicConfig将删除所有现有处理程序,然后在根目录上配置处理程序。它将始终创建一个格式化程序实例,并在所有处理程序上设置它
您可以使用basicConfig满足所有根记录器需求:
import http.client
import logging
import os.path
import sys
from logging.handlers import TimedRotatingFileHandler
def setup_logging(loglevel):
# the file handler receives all messages from level DEBUG on up, regardless
fileHandler = TimedRotatingFileHandler(
os.path.join(logPath, logFileName + ".log"),
when="midnight"
)
fileHandler.setLevel(logging.DEBUG)
handlers = [fileHandler]
if loglevel is not None:
# if a log level is configured, use that for logging to the console
stream_handler = logging.StreamHandler(sys.stdout)
stream_handler.setLevel(loglevel)
handlers.append(stream_handler)
if loglevel == logging.DEBUG:
# when logging at debug level, make http.client extra chatty too
# http.client *uses `print()` calls*, not logging.
http.client.HTTPConnection.debuglevel = 1
# finally, configure the root logger with our choice of handlers
# the logging level of the root set to DEBUG (defaults to WARNING otherwise).
logformat = "%(asctime)s [%(threadName)-12.12s] [%(levelname)-5.5s] %(message)s"
logging.basicConfig(
format=logformat, datefmt="%Y-%m-%d %H:%M:%S",
handlers=handlers, level=logging.DEBUG
)
旁注:http.client库不使用日志来输出调试消息;它将始终使用“打印”来输出这些内容。如果您想在日志中看到这些消息,则需要对库进行修补,添加一个可选的全局打印:
应用了上面的http.client技巧和setup_loggingloging.DEBUG后,我看到以下日志在stdout上和使用请求时出现在文件中。gethttps://stackoverflow.com/a/58769712/100297:
2019-11-08 16:17:26[主线程][调试]启动新的HTTPS连接1:stackoverflow.com:443
2019-11-08 16:17:27[主线程][调试]发送:b'GET/a/58769712/100297 HTTP/1.1\r\n主机:stackoverflow.com\r\n用户代理:python请求/2.22.0\r\n接受编码:gzip,deflate\r\n接受:/*\r\n连接:保持活动\r\n\r\n
2019-11-08 16:17:27[MainThread][DEBUG]答复:“找到HTTP/1.1 302\r\n”
2019-11-08 16:17:27[主线程][调试]头:缓存控制:专用
2019-11-08 16:17:27[MainThread][DEBUG]头:内容类型:text/html;字符集=utf-8
2019-11-08 16:17:27[主线程][调试]标题:位置:/questions/58738195/python http请求和调试级别日志记录到日志文件/5876971258769712
2019-11-08 16:17:27[主线程][调试]标题:X-Frame-Options:SAMEORIGIN
2019-11-08 16:17:27[主线程][调试]标题:X-Request-Guid:761bd2f8-3e5c-453a-ab46-d01284940541
2019-11-08 16:17:27[主线程][调试]头:严格的传输安全性:最大年龄=15552000
2019-11-08 16:17:27[主线程][调试]标题:功能策略:麦克风“无”;发言者“无”
2019-11-08 16:17:27[主线程][调试]头:内容安全策略:升级不安全的请求;框住祖先的自我https://stackexchange.com
2019-11-08 16:17:27[主线程][调试]头:接受范围:字节
2019-11-08 16:17:27[主线程][调试]头:年龄:0
2019-11-08 16:17:27[主线程][调试]标题:内容长度:214
2019-11-08 16:17:27[主线程][调试]头:接受范围:字节
2019-11-08 16:17:27[主线程][调试]标题:日期:2019年11月8日星期五16:17:27 GMT
2019-11-08 16:17:27[主线程][调试]头:通孔:1.1
2019-11-08 16:17:27[主线程][调试]头:年龄:0
2019-11-08 16:17:27[主线程][调试]头:连接:保持活动状态
2019-11-08 16:17:27[主线程][调试]头:X服务方:cache-lhr7324-LHR
2019-11-08 16:17:27[主线程][调试]头:X缓存:未命中
2019-11-08 16:17:27[维护]
hread][DEBUG]头:X-Cache-Hits:0
2019-11-08 16:17:27[主线程][调试]头:X定时器:S1573229847.069848,VS0,VE80
2019-11-08 16:17:27[主线程][调试]头:变化:快速SSL
2019-11-08 16:17:27[主线程][调试]头:X-DNS-Prefetch-Control:关闭
2019-11-08 16:17:27[主线程][调试]头:设置Cookie:prov=0e92634f-abce-9f8e-1865-0D35EBEC595;domain=.stackoverflow.com;expires=周五,2055年1月1日00:00:00 GMT;路径=/;HttpOnly
2019-11-08 16:17:27[主线程][调试]https://stackoverflow.com:443 GET/a/58769712/100297 HTTP/1.1 302 214
2019-11-08 16:17:27[MainThread][DEBUG]发送:b'GET/questions/58738195/python http请求和调试级别日志到日志文件/58769712 http/1.1\r\nHost:stackoverflow.com\r\n用户代理:python请求/2.22.0\r\n接受编码:gzip,放气\r\n接受:*/*\r\n连接:保持活动\r\n检查:prov=0e92634f-abce-9f8e-1865-0d35ebecc595\r\n\r\n
2019-11-08 16:17:27[MainThread][DEBUG]回复:“HTTP/1.1200正常\r\n”
2019-11-08 16:17:27[主线程][调试]头:缓存控制:专用
2019-11-08 16:17:27[MainThread][DEBUG]头:内容类型:text/html;字符集=utf-8
2019-11-08 16:17:27[MainThread][DEBUG]头:内容编码:gzip
2019-11-08 16:17:27[主线程][调试]标题:上次修改:2019年11月8日星期五16:16:07 GMT
2019-11-08 16:17:27[主线程][调试]标题:X-Frame-Options:SAMEORIGIN
2019-11-08 16:17:27[主线程][调试]标题:X-Request-Guid:5e48399e-a91c-44aa-aad6-00a96014131f
2019-11-08 16:17:27[主线程][调试]头:严格的传输安全性:最大年龄=15552000
2019-11-08 16:17:27[主线程][调试]标题:功能策略:麦克风“无”;发言者“无”
2019-11-08 16:17:27[主线程][调试]头:内容安全策略:升级不安全的请求;框住祖先的自我https://stackexchange.com
2019-11-08 16:17:27[主线程][调试]头:接受范围:字节
2019-11-08 16:17:27[主线程][调试]头:年龄:0
2019-11-08 16:17:27[主线程][调试]标题:内容长度:42625
2019-11-08 16:17:27[主线程][调试]头:接受范围:字节
2019-11-08 16:17:27[主线程][调试]标题:日期:2019年11月8日星期五16:17:27 GMT
2019-11-08 16:17:27[主线程][调试]头:通孔:1.1
2019-11-08 16:17:27[主线程][调试]头:年龄:0
2019-11-08 16:17:27[主线程][调试]头:连接:保持活动状态
2019-11-08 16:17:27[主线程][调试]头:X服务方:cache-lhr7324-LHR
2019-11-08 16:17:27[主线程][调试]头:X缓存:未命中
2019-11-08 16:17:27[主线程][调试]头:X-Cache-Hits:0
2019-11-08 16:17:27[主线程][调试]头:X定时器:S1573229847.189349,VS0,VE95
2019-11-08 16:17:27[MainThread][DEBUG]头:变化:接受编码,快速SSL
2019-11-08 16:17:27[主线程][调试]头:X-DNS-Prefetch-Control:关闭
2019-11-08 16:17:27[主线程][调试]https://stackoverflow.com:443 GET/questions/58738195/python http请求和调试级别日志记录到日志文件/58769712 http/1.1 200 42625
您可以使用以下文件复制此文件:
import requests
import sys
logPath, logFileName = "/tmp", "demo"
level = logging.DEBUG if "-v" in sys.argv else None
setup_logging(level)
requests.get("https://stackoverflow.com/a/58769712/100297")
除了上述代码之外,还添加了。然后,您可以使用python-v将级别设置为verbose,并将其与未设置级别的python进行比较。控制台记录器没有什么特别之处。您确定以前没有调用过basicConfig吗?这里是什么?你能添加一个小的测试脚本来重现这个问题吗?也许可以使用sys.argv中的-d作为在日志级别之间切换的测试,并使用请求向某个对象发出请求。@MartijnPieters我已更新了OP。关于添加参数,我在这里描述的第一期中添加了参数,结果是当前问题。basicConfig仅在详细请求的情况下调用。应始终创建日志文件。您的代码仅将当前记录器设置为调试级别;basicConfig设置根记录器级别。Urllib3没有通过本地记录器对象进行日志记录,它会转到根目录和那里的处理程序。@MartijnPieters那么我需要两个记录器吗?一个用于标准输出,一个用于日志文件?控制台记录器没有什么特别之处。您确定以前没有调用过basicConfig吗?这里是什么?你能添加一个小的测试脚本来重现这个问题吗?也许可以使用sys.argv中的-d作为在日志级别之间切换的测试,并使用请求向某个对象发出请求。@MartijnPieters我已更新了OP。关于添加参数,我在这里描述的第一期中添加了参数,结果是当前问题。basicConfig仅在详细请求的情况下调用。应始终创建日志文件。您的代码仅将当前记录器设置为调试级别;basicConfig设置根记录器级别。Urllib3没有通过您的本地记录器对象进行日志记录,它会转到根目录和那里的处理程序。@MartijnPieters那么我需要两个吗
那么loggers-一个用于标准输出,一个用于日志文件?在上述情况下,_logger=logging.getLogger发生了什么?在这种情况下,我应该如何称呼“记录器”?@JackTheKnife:你仍然可以自由使用自己的记录器,只是不要在上面放置处理程序。如果您有其他代码调用_logger.log或任何特定于级别的方法,那么这很好。您不会在安装日志记录中使用它。在这种情况下,使用安装日志记录可以根据传递到控制台的级别将详细信息传递到控制台,而登录到文件将使其保持在调试级别。我试图使用您的解决方案,但没有从中生成到控制台或文件的日志。@JackTheKnife:是的,文件处理程序专门配置为使用级别调试。我刚才试过了,效果和预期的一样。@JackTheKnife:你确定basicConfig还没有被调用吗?您可以将force=True添加到basicConfig调用中,让它删除所有以前的处理程序并强制设置您自己的处理程序?在这种情况下,我应该如何称呼“记录器”?@JackTheKnife:你仍然可以自由使用自己的记录器,只是不要在上面放置处理程序。如果您有其他代码调用_logger.log或任何特定于级别的方法,那么这很好。您不会在安装日志记录中使用它。在这种情况下,使用安装日志记录可以根据传递到控制台的级别将详细信息传递到控制台,而登录到文件将使其保持在调试级别。我试图使用您的解决方案,但没有从中生成到控制台或文件的日志。@JackTheKnife:是的,文件处理程序专门配置为使用级别调试。我刚才试过了,效果和预期的一样。@JackTheKnife:你确定basicConfig还没有被调用吗?您可以将force=True添加到basicConfig调用中,让它删除所有以前的处理程序,并强制设置您自己的处理程序。