Python Logger : StreamHandler not controlling my terminal stdout?

Question:

I’ve got – I believe – a rather standard logger config with two Handlers : file and stream. The file handler works very nicely and I can control the content of the output file with its own level, but the stream handler does not seem to do anything, all root logs are passed to stdout whether I add the StreamHandler or not. Anyone would know what I did wrong ?

I’m running python3.10 on Ubuntu 20.04, here is the config:

import logging
import sys

# root logger
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
# terminal logger
stream_handler = logging.StreamHandler()
stream_handler.setLevel(logging.CRITICAL)
logger.addHandler(stream_handler)
# file logger
file_handler = logging.FileHandler(f'logs/{__name__}.txt', 'w')
file_handler.setLevel(logging.DEBUG)
logger.addHandler(file_handler)

I tried to pass sys.stdout as a parameter for StreamHandler() but it did not change the result.
With the above I would expect the console to only print CRITICAL but it shows all levels:

DEBUG:network:deserialized data: ['111', 'idle', 'normal']
INFO:network:ID:100 ['normal'] already exists, storing server_states[587]: (-13, 2890, 35, 69)
DEBUG:network:_entity.position.server_states={583: <rect(-17, 2713, 35, 69)>}
INFO:network:sending:100|idle['normal']|480;971;35;69|right|0|0|1000.0|3|None|0|0;0|0;0;0;0;0;0
INFO:network:received:107|idle['normal','collectable']12;2935;35;69|left|0|0|1000.0|3|None|45.1

I’m wondering if it would be related to the logger name (dynamic from module name) ?

Asked By: Deux

||

Answers:

Your configuration should work as expected. This slightly modified script:

import logging
import sys

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
# terminal logger
stream_handler = logging.StreamHandler(sys.stdout)
stream_handler.setLevel(logging.CRITICAL)
logger.addHandler(stream_handler)
# file logger
file_handler = logging.FileHandler(f'logs/{__name__}.txt', 'w')
file_handler.setLevel(logging.DEBUG)
logger.addHandler(file_handler)
for level in (logging.DEBUG, logging.INFO, logging.WARNING,
              logging.ERROR, logging.CRITICAL):
    if level:
        logger.log(level, "Event at %s", logging.getLevelName(level))

works as expected, as shown here:

$ python3.10 test_71641676.py > tmp.txt
$ more tmp.txt
Event at CRITICAL

which shows that sys.stdout is being used for the StreamHandler.

Answered By: Vinay Sajip

It seems it is related to the fact that I have multiple modules – each module can have a logger to console, but the main script must remain in control and have its own logger set (which I did not have).
This page solved my problem: https://docs.python.org/3/howto/logging-cookbook.html#logging-to-multiple-destinations

Answered By: Deux
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.