pytest-catchlog
pytest-catchlog copied to clipboard
Handling of loggers with propagate=False
What is the recommended way to handle loggers that are configured with propagate=False
, which appears to cause the message not to reach the caplog handler?
I can manually change the propagate
setting in the test (setup), but there might be a better way?!
import logging
logging.getLogger('project.app').propagate = True
Could pytest-catchlog take care of this automatically, e.g. by attaching its handler to all loggers with propagate=False
?
Would it be feasible to have something like caplog.with_logger
, where you could pass in a logger name and caplog would attach it's handler there directly?
This seems to do the trick:
@pytest.yield_fixture
def caplog(caplog):
import logging
restore = []
for logger in logging.Logger.manager.loggerDict.values():
try:
if not logger.propagate:
restore += [(logger, logger.propagate)]
logger.propagate = True
except AttributeError:
pass
yield caplog
for logger, value in restore:
logger.propagate = value
It might be better to add the caplog handler to the loggers with propagate=False
(logger.addHandler(caplog.handler)
), but that resulted in some ValueError: I/O operation on closed file
, and the handler is probably not meant to be used like that.
Sound good! I wish I had more spare time time to investigate that...
FWIW, this is the current function I am using:
@pytest.yield_fixture
def caplog(caplog):
import logging
restore = []
for logger in logging.Logger.manager.loggerDict.values():
try:
if not logger.propagate:
logger.propagate = True
restore += [logger]
except AttributeError:
pass
yield caplog
for logger in restore:
logger.propagate = False
My solution is:
@contextlib.contextmanager
def caplog_for_logger(caplog, logger_name):
caplog.clear()
caplog.set_level(logging.CRITICAL) # Mute the root-logger
logger = logging.getLogger(logger_name)
logger.addHandler(caplog.handler)
yield
logger.removeHandler(caplog.handler)
def test_foobar(self, caplog):
with caplog_for_logger(caplog, 'my-logger-name):
# testing ....