Pytest and caplog doesn't work if InterceptHandler exists
See original GitHub issueI would like route all logs through loguru and configure them as I see fit, and for that I have created an InterceptHandler
as descriped here.
I also want to test the output of some of my logs via the caplog trick described here.
It seems that I can’t have both at the same time, as it creates a hanging loop.
Is there another way to test the contents of the logs when using an InterceptHandler
?
Issue Analytics
- State:
- Created 2 years ago
- Reactions:1
- Comments:14 (7 by maintainers)
Top Results From Across the Web
Pytest caplog works with custom logger when created with a ...
I have been testing my custom loggers with Pytest. Created a custom logger from Yaml config file, and wrote the following test:
Read more >loguru Documentation - Read the Docs
Loguru is a library which aims to bring enjoyable logging in Python. Did you ever feel lazy about configuring a logger and used...
Read more >How to manage logging — pytest documentation
Setting log_level will set the level that is captured globally so if a specific test requires a lower level than this, use the...
Read more >loguru Documentation
Loguru is a library which aims to bring enjoyable logging in Python. Did you ever feel lazy about configuring a logger and used...
Read more >loguru.logger.add Example - Program Talk
Here are the examples of the python api loguru.logger.add taken from open source ... -things-work-with-pytest-and-caplog """ class PropogateHandler(logging.
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Thanks for the reproducible example, @mehd-io! It’s all clear now.
Basically, Loguru’s handlers are made thread-safe by using a
Lock
to protect concurrent access of sinks. While processing a log message, the handler first acquires theLock
and release it once the message is logged. If another message tries to be logged at the same time, it won’t be handled and will wait until theLock
is released.You’re facing a dead-lock due to recursive call of
logger.log()
. It is very similar to the following scenario:The program is hanging because the
debug()
call is waiting for theLock
acquired byinfo()
to be released, which never happens becausemy_custom_sink()
can’t terminate.In your case, an
InterceptHandler()
is attached to the standard rootlogger
. Every message logged using the standardlogging
library will also be processed by Loguru added handlers. That’s fine, but there’s also aPropagateHandler()
which causes every Loguru message to be propagated to standardlogging
.Consequently, when
logger.info()
is used, theLock
of thePropagateHandler()
is acquired, then the log message is sent to the logger returned bylogging.getLogger(record.name)
which itself call theemit()
function of theInterceptHandler()
. The latter will tries to calllogger.log()
but will hang forever because theLock
is still not released.If this wasn’t hanging you would face infinite recursion anyway.
I never realized it, but
InterceptHandler
andPropagateHandler
don’t mix well.The solution is to find a trick so that the
InterceptHandler
does not process the messages generated by thePropagateHandler
. I can suggest the following updated handlers:I’m not entirely satisfied with this solution, but this is the best I’ve found so far.
I confirm that the workaround works 🎉 , thanks @Delgan for the awesome support & library 🙌