Python 跑单元测试时如何禁用日志输出?
测试时刷屏的日志可以用 logging.disable(logging.CRITICAL) 全局静音,pytest 则可用 -p no:logging 或配置 log_cli。本文介绍两种思路及恢复方法。
最省事的方式是在测试入口调用 logging.disable(logging.CRITICAL)——它会全局屏蔽 CRITICAL 以下所有级别的日志;测试结束用 logging.disable(logging.NOTSET) 恢复。pytest 用户还可以用 --show-capture=no 或在配置里关掉 log_cli。
方法一:全局禁用 logging
import logging
logging.disable(logging.CRITICAL) # 之后所有 <= CRITICAL 的日志都不输出
# ... 运行测试 ...
logging.disable(logging.NOTSET) # 恢复正常
logging.disable(level) 是官方提供的"总开关",比挨个调 logger 级别彻底得多。
方法二:pytest 的日志控制
pytest 默认会捕获日志并在用例失败时展示。如果嫌输出太多:
pytest -p no:logging # 禁用 pytest 的日志捕获插件
pytest --show-capture=no # 失败时也不显示捕获的 stdout/日志
或在 pytest.ini 中关闭实时日志:
[pytest]
log_cli = false
方法三:移除 handler(精细控制)
logger = logging.getLogger()
handlers = logger.handlers[:]
logger.handlers = []
# ... 运行测试 ...
logger.handlers = handlers
适合只想静音某些 handler(比如控制台)但保留文件日志的场景。
常见问题(FAQ)
Q:logging.disable 和 setLevel 有什么区别?
A:disable 是全局开关,作用于所有 logger,性能也最好(消息在源头就被丢弃);setLevel 针对单个 logger。测试场景用前者更干净。
Q:禁用后如何验证"代码确实打了日志"?
A:这正是问题所在——建议配合 unittest.mock 断言 logger 被调用,或用 pytest 的 caplog fixture 断言日志内容,而不是靠肉眼看输出。
Q:Django 测试时也想静音?
A:在测试 settings 里把 LOGGING 的 root logger 级别调高,或用 override_settings;Django 还会默认重置 logging 配置,可设 LOGGING_CONFIG = None 接管。