Structlog与logging模块在pytest中无法生成日志的问题排查
structlog日志在pytest中无输出问题排查
问题场景
测试目录结构:
├── tests │ ├── __init__.py │ ├── conftest.py │ ├── test_main.py
tests/__init__.py中的日志配置:
import structlog, logging, sys from structlog.testing import LogCapture logging.basicConfig(filename="test.log", filemode="w") structlog.configure( processors=[LogCapture()], context_class=structlog.threadlocal.wrap_dict(dict), logger_factory=structlog.stdlib.LoggerFactory(), cache_logger_on_first_use=True )
test_main.py内容:
import logging, structlog, pytest from src.factories.factories import MyFactory import src.main from pathlib import Path from datetime import datetime @pytest.mark.parametrize( "factory", [ MyFactory(), ], ) def test_main(path_to_results_folder_fixture_in_conftest, factory): structlog.get_logger().info("test") no_of_files_function = lambda: sum(1 for _ in Path(path_to_results_folder_fixture_in_conftest).iterdir()) len_before = no_of_files_function() src.main.main("sony", factory, path_to_results_folder) assert no_of_files_function() == len_before + 1
运行pytest test_main.py后,test.log为空,控制台也无日志输出,但预期structlog.get_logger().info("test")应生成日志内容。
问题原因及修复方法
核心问题
LogCapture处理器的作用限制:你将structlog.testing.LogCapture作为唯一处理器,它的功能是在内存中捕获日志供测试断言使用,不会将日志传递给标准logging系统,自然无法写入文件或输出到控制台。- 日志级别未显式配置:
logging.basicConfig默认日志级别为WARNING,你输出的INFO级别日志会被默认过滤掉。 - structlog未连接到标准输出流程:现有配置没有搭建从structlog到标准logging的输出链路,导致
logging.basicConfig的文件输出配置无效。
修复步骤
方案1:保留日志捕获+输出日志
如果你既需要在测试中捕获日志做断言,又要输出日志到文件,可以修改tests/__init__.py的配置:
import structlog, logging, sys from structlog.testing import LogCapture # 配置标准logging,显式设置INFO级别 logging.basicConfig( filename="test.log", filemode="w", format="%(message)s", level=logging.INFO ) structlog.configure( processors=[ LogCapture(), # 保留日志捕获功能 structlog.stdlib.add_log_level, # 添加日志级别字段 structlog.processors.TimeStamper(fmt="iso"), # 可选:添加时间戳 structlog.stdlib.ProcessorFormatter.wrap_for_formatter, # 连接到标准logging格式器 ], context_class=structlog.threadlocal.wrap_dict(dict), logger_factory=structlog.stdlib.LoggerFactory(), cache_logger_on_first_use=True )
方案2:仅输出日志(无需捕获)
如果不需要在测试中断言日志内容,直接移除LogCapture处理器,改用常规输出配置:
import structlog, logging, sys logging.basicConfig( filename="test.log", filemode="w", format="%(message)s", level=logging.INFO ) structlog.configure( processors=[ structlog.stdlib.add_log_level, structlog.processors.TimeStamper(fmt="iso"), structlog.stdlib.render_to_log_kwargs, # 将structlog日志转换为标准logging参数 ], context_class=dict, logger_factory=structlog.stdlib.LoggerFactory(), cache_logger_on_first_use=True )
额外代码修复
测试函数中存在未定义变量:path_to_results_folder应该替换为path_to_results_folder_fixture_in_conftest,否则运行时会抛出NameError。
内容的提问来源于stack exchange,提问作者aldo
相关产品推荐
相关产品推荐

