如何在pytest中抑制第三方日志

jon*_*two 8 python logging nose pytest

我们刚刚从 切换nosepytest并且似乎没有抑制第三方日志记录的选项。在nose配置中,我们有以下行:

logging-filter=-matplotlib,-chardet.charsetprober,-PIL,-fiona.env,-fiona._env
Run Code Online (Sandbox Code Playgroud)

其中一些日志非常啰嗦,尤其是matplotlib我们不想看到输出,只想从我们的日志中输出。

但是我找不到等效的设置pytest。是否可以?我错过了什么吗?谢谢。

Ana*_*lii 6

我这样做的方法是创建一个记录器名称列表,必须在conftest.py 中禁用其日志。

例如,如果我想禁用一个名为 的记录器app,那么我可以编写如下的conftest.py

import logging

disable_loggers = ['app']

def pytest_configure():
    for logger_name in disable_loggers:
        logger = logging.getLogger(logger_name)
        logger.disabled = True
Run Code Online (Sandbox Code Playgroud)

然后运行我的测试:

import logging

def test_brake():
    logger = logging.getLogger("app")
    logger.error("Hello there")
    assert True
Run Code Online (Sandbox Code Playgroud)

收集 ... 收集 1 项

test_car.py::test_brake PASSED
[100%]

============================== 1 在 0.01 秒内通过 ================ ================

然后,您好,那里没有,因为appconftest.py中禁用了具有该名称的记录器。

但是,如果我将测试中的记录器名称更改为app2并再次运行测试:

import logging

def test_brake():
    logger = logging.getLogger("app2")
    logger.error("Hello there")
    assert True
Run Code Online (Sandbox Code Playgroud)

收集 ... 收集 1 项

test_car.py::test_brake -------------------------------- 实时日志调用 --------- ------------------------ 错误 app2:test_car.py:5你好,已通过
[100%]

============================== 1 在 0.01 秒内通过 ================ ================

如您所见,您好,因为app2没有禁用记录器。

结论

基本上,您可以执行相同的操作,但只需将不需要的记录器名称添加到conftest.py 中,如下所示:

import logging

disable_loggers = ['matplotlib', 'chardet.charsetprober', <add more yourself>]

def pytest_configure():
    for logger_name in disable_loggers:
        logger = logging.getLogger(logger_name)
        logger.disabled = True
Run Code Online (Sandbox Code Playgroud)


Mid*_*ter 3

除了调整日志记录级别或根本不显示任何日志输出的能力(我确信您已经在文档中阅读过)之外,想到的唯一方法是一般配置日志记录。

假设所有这些包都使用标准库日志记录工具,您可以使用多种选项来配置记录的内容。请查看高级教程,以更好地了解您的选项。

如果您不想在一般情况下为应用程序配置日志记录,而只想在测试期间配置日志记录,则可以使用pytest_configurepytest_sessionstart挂钩来执行此操作,您可以将它们放置在conftest.py测试文件层次结构的根目录中。

然后我看到三个选项:

  1. 强力方法是使用默认行为fileConfigdictConfig禁用所有现有记录器。在你的conftest.py

    import logging.config
    
    
    def pytest_sessionstart():
        # This is the default so an empty dictionary should work, too.
        logging.config.dictConfig({'disable_existing_loggers': True})
    
    Run Code Online (Sandbox Code Playgroud)
  2. 更微妙的方法是更改​​单个记录器的级别或禁用它们。举个例子:

    import logging.config
    
    
    def pytest_sessionstart():
        logging.config.dictConfig({
            'disable_existing_loggers': False,
            'loggers': {
                # Add any noisy loggers here with a higher loglevel.
                'matplotlib': {'level': 'ERROR'}
            }
        })
    
    Run Code Online (Sandbox Code Playgroud)
  3. 最后,您可以使用pytest_addoption挂钩添加与您提到的类似的命令行选项。同样,在测试层次结构的根部将以下内容放入conftest.py

    def pytest_addoption(parser):
        parser.addoption(
            "--logging-filter",
            help="Provide a comma-separated list of logger names that will be "
            "disabled."
        )
    
    
    def pytest_sessionstart(pytestconfig):
        for logger_name in pytestconfig.getoption("--logging-filter").split(","):
            # Use `logger_name.trim()[1:]` if you want the `-name` CLI syntax.
            logger = logging.getLogger(logger_name.trim())
            logger.disabled = True
    
    Run Code Online (Sandbox Code Playgroud)

    然后您可以通过以下方式调用 pytest:

    pytest --logging-filter matplotlib,chardet,...
    
    Run Code Online (Sandbox Code Playgroud)

pytest 的默认方法是隐藏所有日志,但提供caplog固定装置来检查测试用例中的日志输出。如果您正在寻找特定的日志行,这将非常强大。所以问题还在于为什么您需要在测试套件中查看这些日志?