Python – logging setLevel, how it works

loggingpython

In the logging howto documentation there is this example:

import logging

# create logger
logger = logging.getLogger('simple_example')
logger.setLevel(logging.DEBUG)

# create console handler and set level to debug
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)

# create formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# add formatter to ch
ch.setFormatter(formatter)

# add ch to logger
logger.addHandler(ch)

Why I should set the level to logging.DEBUG twice, for Logger, and for the StreamHandler?

I understand ch.setLevel(logging.DEBUG) will set the debug level for the stream handler. But what the effect is of setting the level to logger? Where this level is reflected?

I get the same console output if I change the level to, for example, INFO either to the Logger or to the StreamHandler.

That is:

...........
logger.setLevel(logging.INFO)
............
ch.setLevel(logging.DEBUG)

gives the same output in console than

...........
logger.setLevel(logging.DEBUG)
............
ch.setLevel(logging.INFO)

Best Solution

It's there for fine-tuning (you can have multiple handlers, and each could have different levels set) — you can safely not set level on the handler, which will cause it to process all messages (a.k.a. NOTSET level), and leave level filtering to the logger.

Logger is also the first to filter the message based on a level — if you set the logger to INFO, and all handlers to DEBUG, you still won't receive DEBUG messages on handlers — they'll be rejected by the logger itself. If you set logger to DEBUG, but all handlers to INFO, you won't receive any DEBUG messages either — because while the logger says "ok, process this", the handlers reject it (DEBUG < INFO).