Disabling specific logger in pytest
Question:
In my project I’m parsing some PDF files using pdfplumber. During tests execution (pytest) I sometimes would like to see logs from my code for debugging purposes. This can be done by setting --log-cli-level=DEBUG
. However, this turns on messages from all code, also pdfplumber – which is very verbose and makes debugging difficult. Is there a way to selectively enable/disable loggers during test run?
pytest 4.6.3
python 3.7.3
Thanks for help!
Answers:
No, pytest won’t be able to do this for you as far as I know and can see. What I can think of is introducing your own environment variables and change log levels accordingly. Something like this:
import os
import logging
logger = logging.getLogger('mylogger')
if os.environ.get('mylogger_level'):
logger.setLevel(os.environ.get('mylogger_level'))
Pytest does not support this by default, but you can add a custom option to your conftest.py
to turn off specific loggers.
import pytest
import logging
def pytest_addoption(parser):
"""Add a command line option to disable logger."""
parser.addoption(
"--log-disable", action="append", default=[], help="disable specific loggers"
)
def pytest_configure(config):
"""Disable the loggers."""
for name in config.getoption("--log-disable", default=[]):
logger = logging.getLogger(name)
logger.propagate = False
I has doing this on a per-test basis with this:
ddef with_logs(**loggers):
def all_loggers():
import logging_tree
def visit(node):
yield node[0]
for child in node[2]:
yield from visit(child)
return set(visit(logging_tree.nodes.tree()))
unknown_loggers = set(loggers) - all_loggers()
if unknown_loggers:
raise ValueError(f"Unknown loggers: {unknown_loggers}")
def decorate(f):
def disable(logger):
logging.getLogger(logger).setLevel(logging.INFO)
def enable(logger):
logging.getLogger(logger).setLevel(logging.DEBUG)
disabled_loggers = []
for k, v in loggers.items():
if not v:
disabled_loggers.append(k)
@functools.wraps(f)
def wrapped(*args, **kwargs):
for logger in disabled_loggers:
disable(logger)
try:
return f(*args, **kwargs)
finally:
for logger in disabled_loggers:
enable(logger)
return wrapped
return decorate
...
@with_logs(logger1=False, logger2=False)
def test_x():
In my project I’m parsing some PDF files using pdfplumber. During tests execution (pytest) I sometimes would like to see logs from my code for debugging purposes. This can be done by setting --log-cli-level=DEBUG
. However, this turns on messages from all code, also pdfplumber – which is very verbose and makes debugging difficult. Is there a way to selectively enable/disable loggers during test run?
pytest 4.6.3
python 3.7.3
Thanks for help!
No, pytest won’t be able to do this for you as far as I know and can see. What I can think of is introducing your own environment variables and change log levels accordingly. Something like this:
import os
import logging
logger = logging.getLogger('mylogger')
if os.environ.get('mylogger_level'):
logger.setLevel(os.environ.get('mylogger_level'))
Pytest does not support this by default, but you can add a custom option to your conftest.py
to turn off specific loggers.
import pytest
import logging
def pytest_addoption(parser):
"""Add a command line option to disable logger."""
parser.addoption(
"--log-disable", action="append", default=[], help="disable specific loggers"
)
def pytest_configure(config):
"""Disable the loggers."""
for name in config.getoption("--log-disable", default=[]):
logger = logging.getLogger(name)
logger.propagate = False
I has doing this on a per-test basis with this:
ddef with_logs(**loggers):
def all_loggers():
import logging_tree
def visit(node):
yield node[0]
for child in node[2]:
yield from visit(child)
return set(visit(logging_tree.nodes.tree()))
unknown_loggers = set(loggers) - all_loggers()
if unknown_loggers:
raise ValueError(f"Unknown loggers: {unknown_loggers}")
def decorate(f):
def disable(logger):
logging.getLogger(logger).setLevel(logging.INFO)
def enable(logger):
logging.getLogger(logger).setLevel(logging.DEBUG)
disabled_loggers = []
for k, v in loggers.items():
if not v:
disabled_loggers.append(k)
@functools.wraps(f)
def wrapped(*args, **kwargs):
for logger in disabled_loggers:
disable(logger)
try:
return f(*args, **kwargs)
finally:
for logger in disabled_loggers:
enable(logger)
return wrapped
return decorate
...
@with_logs(logger1=False, logger2=False)
def test_x():