You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pytest caplog无法捕获日志问题求助(附复现代码)

Pytest caplog无法捕获日志问题解决

问题背景

我在使用Pytest的caplog插件时遇到了无法捕获日志的问题,以下是最小复现代码、执行输出和环境信息:

复现代码

import logging
import logging.config


def test_logging(caplog):
    LOGGING_CONFIG = {
        "version": 1,
        "disable_existing_loggers": False,
        "formatters": {
            "default": {
                "format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
            },
        },
        "handlers": {
            "console": {
                "class": "logging.StreamHandler",
                "formatter": "default",
                "level": "DEBUG",
            },
        },
        "loggers": {
            "": {  # root logger
                "handlers": ["console"],
                "level": "DEBUG",
                "propagate": True,
            },
        },
    }

    logging.config.dictConfig(LOGGING_CONFIG)

    logger = logging.getLogger("root_module.sub1.sub2")
    logger.setLevel(logging.DEBUG)

    assert logger.propagate is True
    assert logger.getEffectiveLevel() == logging.DEBUG

    with caplog.at_level(logging.DEBUG):
        logger.debug("🔥 DEBUG msg")
        logger.info("📘 INFO msg")
        logger.warning("⚠️ WARNING msg")
        logger.error("❌ ERROR msg")
        logger.critical("💀 CRITICAL msg")

    print("🔥 caplog.messages:", caplog.messages)

    # Final assertion
    assert any("CRITICAL" in r or "💀" in r for r in caplog.messages)

执行pytest -s输出

tests/test_logs.py 2025-04-16 17:06:03,983 - root_module.sub1.sub2 - DEBUG - 🔥 DEBUG msg
2025-04-16 17:06:03,983 - root_module.sub1.sub2 - INFO - 📘 INFO msg
2025-04-16 17:06:03,983 - root_module.sub1.sub2 - WARNING - ⚠️ WARNING msg
2025-04-16 17:06:03,983 - root_module.sub1.sub2 - ERROR - ❌ ERROR msg
2025-04-16 17:06:03,983 - root_module.sub1.sub2 - CRITICAL - 💀 CRITICAL msg
🔥 caplog.messages: []

环境信息

  • Pytest版本:8.3.5
  • setup.cfg配置:
[tool:pytest]
testpaths =
    tests

预期caplog.records包含全部5条日志,但实际为空列表。


问题原因

调用logging.config.dictConfig()时,你重新配置了root logger的handlers,仅保留了自定义的console handler,而Pytest的caplog插件原本会自动向root logger添加一个专属的日志handler,这个handler被你的配置覆盖移除了,所以caplog无法再捕获任何日志。

解决方案

方案1:在dictConfig中保留caplog的handler

在配置root logger的handlers时,把caplog的handler也包含进去。修改LOGGING_CONFIG中的root logger部分:

"loggers": {
    "": {  # root logger
        "handlers": ["console"] + [h for h in logging.getLogger().handlers if hasattr(h, 'caplog')],
        "level": "DEBUG",
        "propagate": True,
    },
},

这样既能保留你的console输出,也不会移除caplog的handler。

方案2:避免重新配置root logger,只配置目标logger

如果不需要修改root logger的配置,可以只针对root_module.sub1.sub2这个logger进行配置,而不是覆盖root logger:

LOGGING_CONFIG = {
    "version": 1,
    "disable_existing_loggers": False,
    "formatters": {
        "default": {
            "format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
        },
    },
    "handlers": {
        "console": {
            "class": "logging.StreamHandler",
            "formatter": "default",
            "level": "DEBUG",
        },
    },
    "loggers": {
        "root_module.sub1.sub2": {  # 仅配置目标logger
            "handlers": ["console"],
            "level": "DEBUG",
            "propagate": True,
        },
    },
}

这样root logger的caplog handler会被保留,日志会通过propagate传递到root logger,从而被caplog捕获。

方案3:在dictConfig后重新添加caplog的handler

如果必须重新配置root logger,可以在调用dictConfig之后,把caplog的handler重新添加到目标logger或root logger上:

logging.config.dictConfig(LOGGING_CONFIG)

# 获取caplog的handler并添加到目标logger
for handler in caplog.handlers:
    logger.addHandler(handler)

这样目标logger的日志会同时发送到console和caplog的handler,保证捕获生效。


内容的提问来源于stack exchange,提问作者Elgin Cahangirov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 09:48:09