Python 跑单元测试时如何禁用日志输出?
测试时刷屏的日志可以用 logging.disable(logging.CRITICAL) 屏蔽标准级别;pytest 禁用日志插件或 log_cli 仅影响相应捕获/展示。本文介绍两种思路及恢复方法。
最省事的方式是在测试入口调用 logging.disable(logging.CRITICAL)——它会屏蔽标准 logging 中数值小于等于 CRITICAL 的级别(更高自定义级别及直接 print 不在此范围)的日志;测试结束恢复原先保存的 disable 门槛。pytest 用户还可以用 --show-capture=no 或在配置里关掉 log_cli。
方法一:全局禁用 logging
import logging
previous = logging.root.manager.disable
try:
logging.disable(logging.CRITICAL)
# ... 运行测试 ...
finally:
logging.disable(previous) # 恢复原门槛,而非无条件重置
logging.disable(level) 是官方提供的"总开关",比挨个调 logger 级别彻底得多。
方法二:pytest 的日志控制
pytest 默认会捕获日志并在用例失败时展示。如果嫌输出太多:
pytest -p no:logging # 禁用 pytest 的日志捕获插件
pytest --show-capture=no # 失败时也不显示捕获的 stdout/日志
或在 pytest.ini 中关闭实时日志:
[pytest]
log_cli = false
禁用 pytest 日志插件不等于静音应用的 handler,并会影响 caplog 可用性;--show-capture=no 只隐藏捕获内容展示,log_cli=false 只关闭实时日志。
方法三:移除 handler(精细控制)
logger = logging.getLogger()
handlers = logger.handlers[:]
try:
logger.handlers = []
# ... 运行测试 ...
finally:
logger.handlers = handlers
上例移除了 root 上全部 handler,不能保留其文件日志,其他 logger 自带 handler 和 lastResort 仍可能输出。只想静音控制台时应选择明确的控制台 handler 调整,并保护 pytest 的捕获 handler。
常见问题(FAQ)
Q:logging.disable 和 setLevel 有什么区别?
A:disable 是全局开关,作用于所有 logger,会在 Logger 级别检查时屏蔽,不能未经测量断言性能最好;setLevel 针对单个 logger。测试场景用前者更干净。
Q:禁用后如何验证"代码确实打了日志"?
A:这正是问题所在——建议配合 unittest.mock 断言 logger 被调用,或保留 pytest 日志插件并在被测代码执行前恢复合适门槛,用 caplog 断言内容,而不是靠肉眼看输出。
Q:Django 测试时也想静音?
A:在测试 settings 里把 LOGGING 的 root logger 级别调高,需在 Django 初始化时应用实际 logging 配置;override_settings(LOGGING=...) 不保证自动重跑 dictConfig。LOGGING_CONFIG = None 仅关闭 Django 自动配置,不会清空已有 logger。
[1]: 观测云文档《日志查看器》https://docs.guance.com/logs/explorer/