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

使用pytest时如何移除loguru.logger的日志处理器?

解决Loguru在Pytest测试中写入日志文件的问题

问题场景

我用Loguru实现了一个Thing类,在类文件末尾给logger添加了写入thing.log的处理器,代码如下:

from loguru import logger


class Thing:
    def __init__(self):
        logger.info("Thing created")

    def __enter__(self):
        logger.info("Thing entered")
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        logger.info("Thing exited")


logger.add("thing.log")

if __name__ == "__main__":
    with Thing() as thing:
        logger.info("In with block")

正常运行时日志会写入thing.log,但执行Pytest测试时,我希望只使用Loguru默认的标准输出(stdout),不要生成这个日志文件。现有的测试代码能通过,但日志依然会写入thing.log,尝试过多种patch方式都无法解决。

解决方案

方法1:调整原代码,仅在直接运行时添加日志处理器

把logger.add("thing.log")放到if __name__ == "__main__"代码块内,这样测试导入Thing类时不会执行添加文件处理器的逻辑:

from loguru import logger


class Thing:
    def __init__(self):
        logger.info("Thing created")

    def __enter__(self):
        logger.info("Thing entered")
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        logger.info("Thing exited")


if __name__ == "__main__":
    logger.add("thing.log")
    with Thing() as thing:
        logger.info("In with block")

这种方式最简洁,符合Python模块导入的设计逻辑,测试环境不会加载生产环境的日志配置。

方法2:测试后清理Loguru的额外处理器

如果不想修改原代码,可以编写一个自动执行的fixture,在测试结束后移除所有非默认的日志处理器:

import pytest
from loguru import logger
from thing import Thing


@pytest.fixture(autouse=True)
def clear_loguru_handlers():
    # 保存默认的标准输出处理器ID
    default_handler_ids = [handler.id for handler in logger._core.handlers.values()]
    yield
    # 移除所有非默认的处理器
    for handler_id in list(logger._core.handlers.keys()):
        if handler_id not in default_handler_ids:
            logger.remove(handler_id)


@pytest.fixture
def thing():
    with Thing() as thing:
        yield thing


def test_thing(thing):
    logger.info("In test")
    assert isinstance(thing, Thing)

方法3:Mock Loguru的add方法

通过mock阻止logger.add执行实际的处理器添加操作,这样导入thing模块时不会创建日志文件:

import pytest
from loguru import logger
from thing import Thing


@pytest.fixture(autouse=True)
def mock_loguru_add(mocker):
    # 拦截logger.add调用,不执行实际操作
    mocker.patch("loguru.logger.add")


@pytest.fixture
def thing():
    with Thing() as thing:
        yield thing


def test_thing(thing):
    logger.info("In test")
    assert isinstance(thing, Thing)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 01:15:37