pytest默认捕获stdout/stderr以避免日志干扰结果判断,故print和logging不显示;调试时可用-s --log-cli-level=info或配置pytest.ini启用实时输出。

pytest默认不显示print和logging输出,为什么?
因为pytest默认启用-s(禁用输出捕获)的反向行为——它会捕获stdout和stderr,导致print()、logging.info()等调用在终端“消失”,只在测试失败时才展示。这不是bug,是设计:避免大量日志干扰结果判断。但调试时这就成了障碍。
让pytest显示所有print和logging输出的两种可靠方式
最常用且无副作用的是命令行开关,适合临时调试;配置文件方式适合团队统一规范。
- 运行时加
--capture=no或简写-s:pytest -s test_example.py—— 此时所有print()实时输出,但logging仍可能被抑制(取决于log level和handler) - 同时捕获并显示
logging需额外加--log-cli-level=INFO(或DEBUG):pytest -s --log-cli-level=INFO test_example.py - 写入
pytest.ini更省事:[tool:pytest] log_cli = true log_cli_level = INFO log_cli_format = %(asctime)s [%(levelname)8s] %(name)s: %(message)s log_cli_date_format = %Y-%m-%d %H:%M:%S console_output_style = classic
注意log_cli = true比log_cli = 1更稳妥,部分旧版本不识别数值
logging.getLogger()没输出?检查root logger和handler
即使开了--log-cli-level,自定义logger仍可能静默——常见原因是没把handler加到root logger,或level设得太高。
- 确保你的logger最终传播到root:
logger.propagate = True(默认就是True,但显式设更安心) - 别手动调用
logging.basicConfig(),它会干扰pytest内置的log handler初始化 - 如果用了
logging.getLogger("my_module"),但没设置level,它继承root level(默认WARNING),而你发的是logger.info("msg")→ 不会输出。显式设logger.setLevel(logging.INFO) - 验证是否生效:在测试里加一行
import logging; logging.getLogger().handlers,看是否至少有一个pytest.logging.LogCaptureHandler
CI环境里print能看见,logging却消失?注意log level和格式冲突
CI流水线(如GitHub Actions)常默认关闭ANSI颜色、截断长行,还会把logging的%(asctime)s格式化为空字符串,导致整条日志被判定为“空行”而过滤掉。
- CI中优先用
--log-cli-level=INFO --log-cli-format="%(levelname)s %(name)s %(message)s",避开asctime和name过长问题 - 某些CI runner(如GitLab CI)对stderr有缓冲,加
python -u运行pytest可强制unbuffered:python -u -m pytest -s --log-cli-level=INFO - 若用
caplogfixture做断言,注意它只捕获当前测试函数内的log,不跨setup_method或conftest.py中的日志
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











