logging.basicConfig()仅首次调用生效,后续调用被静默忽略;应统一在主入口配置,改用getLogger()显式设置handler和logger级别,并结合LoggerAdapter、RotatingFileHandler及敏感信息脱敏确保日志可控可靠。

logging.basicConfig() 为什么只生效一次
Python 的 logging.basicConfig() 只在首次调用时生效,后续调用会被忽略。爬虫常在模块初始化、重试逻辑或子线程中反复尝试配置日志,结果发现日志没按预期输出到文件或没显示 DEBUG 级别——大概率是这里被静默跳过了。
- 改用
logging.getLogger()显式获取 logger,再调用handler.setLevel()和logger.setLevel()分别控制处理器和 logger 本身级别 - 避免在循环、重试函数里重复调用
basicConfig() - 如果用多个模块,统一在主入口(如
if __name__ == "__main__":块)中完成基础配置
如何让每个请求都记录 URL、状态码和耗时
直接在 requests.get() 或 session.request() 调用前后打日志,容易漏掉异常路径(比如超时、连接拒绝)。更可靠的方式是封装一层带日志的请求函数,或使用 requests.Session 的 mount() + 自定义 Adapter,但对多数爬虫来说,用 logging.LoggerAdapter 更轻量。
- 定义一个带上下文的 adapter:
adapter = logging.LoggerAdapter(logger, {"url": url, "status": "-", "duration": 0}) - 用
time.perf_counter()包裹请求,捕获异常后仍记录耗时和失败状态 - 在 formatter 中用
%(url)s %(status)s %(duration).3fs即可自动注入,无需每次拼字符串
日志滚动写入与磁盘爆满风险
爬虫跑一晚上可能产生几百 MB 日志,用 FileHandler 直接写会撑爆磁盘。必须用 RotatingFileHandler 或 TimedRotatingFileHandler,但参数选错反而让日志管理更混乱。
- 优先选
RotatingFileHandler:设置maxBytes=10*1024*1024(10MB) +backupCount=5,最多保留 5 个历史文件 - 避免用
TimedRotatingFileHandler按天切分——爬虫可能凌晨三点还在跑,日志名带时间戳反而难定位 - 注意 Windows 下文件被占用时无法轮转,可在
doRollover()前加os.chmod(old_file, stat.S_IWRITE)防止权限锁死
DEBUG 日志泄露敏感信息怎么办
开启 logger.setLevel(logging.DEBUG) 后,requests 库默认会把 headers、cookies、甚至 POST body 打进日志,密码、token、CSRF token 全暴露在明文文件里。
立即学习“Python免费学习笔记(深入)”;
- 禁用 requests 内部 debug 日志:
logging.getLogger("requests.packages.urllib3").setLevel(logging.WARNING) - 自定义 request 函数中,对
data或json参数做脱敏处理(如str(data)[:100] + "..."),不直接传原始对象进logger.debug() - 生产环境永远用
INFO或更高,DEBUG 仅用于本地排查;日志文件权限设为600(Linux/macOS)防止非 owner 读取


















