如何记录 Python requests 库发出的所有 HTTP 请求?
记录 requests 的请求详情:把 urllib3 的 logger 级别设为 DEBUG,配合 HTTPConnection.debuglevel=1 可看到请求发送及响应状态/头部诊断,但通常不转储响应 body。本文介绍配置方法及注意事项。
两步:一、logging.getLogger('urllib3').setLevel(logging.DEBUG) 让 urllib3 输出连接日志;二、HTTPConnection.debuglevel = 1 让 http.client 打印请求发送及响应状态/头部的诊断信息;通常不会完整转储响应 body,不能视为完整抓包。
完整配置
import logging
from http.client import HTTPConnection
# 第一步:urllib3 的 DEBUG 日志
logging.basicConfig(level=logging.DEBUG)
logging.getLogger('urllib3').setLevel(logging.DEBUG)
# 第二步:HTTPConnection 打印请求/响应详情
HTTPConnection.debuglevel = 1
import requests
requests.get('https://httpbin.org/get', timeout=10)
输出通常包含请求行、请求头、发送内容及响应状态/头部,不保证包含响应 body;debuglevel 输出直接走 stdout。
更可控的方式:requests 事件钩子
import requests
import logging
from urllib.parse import urlsplit
logging.basicConfig(level=logging.INFO) # 独立脚本;已有配置时需调整实际 handler
def log_response(response, *args, **kwargs):
logging.info("%s %s -> %s", response.request.method, urlsplit(response.url).hostname, response.status_code)
session = requests.Session()
session.hooks['response'].append(log_response)
session.get('https://httpbin.org/get', timeout=10)
钩子函数在每个响应返回时触发,可以自定义记录哪些字段、输出到哪。没有响应的连接失败和内部每次重试不保证触发 response hook;完整 URL 还可能含敏感查询参数,示例仅记录主机名。
注意事项
- 敏感信息:DEBUG 日志会打印请求头和 body,可能包含 Token、密码等,生产环境慎用;
- 性能:debuglevel=1 会让输出显著增多,仅用于调试;
- 生产替代:生产环境建议用 APM 工具记录 HTTP 调用链路,而不是 DEBUG 日志。
常见问题(FAQ)
Q:只记录请求 URL 和状态码,不要 body?
A:用事件钩子方案,在回调函数中只取需要的字段。
Q:debuglevel=1 的输出能写到文件吗?
A:它的输出直接走 stdout(不走 logging),重定向 stdout 即可;更规范的做法是用钩子方案把日志写入 logging 体系。
Q:requests 自己的 logger 是什么?
A:requests 的日志主要走 urllib3 logger,没有独立的 requests logger 输出请求详情。