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(logg开发者_开发知识库ing.INFO)
............
ch.setLevel(logging.DEBUG)
gives the same output in console than
...........
logger.setLevel(logging.DEBUG)
............
ch.setLevel(logging.INFO)
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).
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?.
This is indicated in the documentation:
"The setLevel() method, just as in logger objects, specifies the lowest severity that will be dispatched to the appropriate destination. Why are there two setLevel() methods? The level set in the logger determines which severity of messages it will pass to its handlers. The level set in each handler determines which messages that handler will send on."
Check under Handlers: http://docs.python.org/2.7/howto/logging.html#logging-advanced-tutorial
I think is useful to consider these main three points to understand how logging works:
You can build a hierarchy of Logger objects. Each of them will initially have no level set (level NOTSET). The effective level of a Logger object is the first level that has been set in the hierarchy on the way up to the root logger (possibly NOTSET, if no level has been set).
The effective level of a Logger, is only used to determine whether to start action with message directly emitted to that logger.
That action is, first, passing the message to that Logger's handlers, and second (depending on the value of the propagate flag), passing it to each of the handlers of the chain of ancestors to the top, without taking into consideration the actual levels of each of the loggers in the chain.
To answer your question, you don't need to set it twice in that example. Setting it to DEBUG only in the Logger will be enough to enable log messages sent directly to your Logger instance to make their way to the console (since the default level in a new StreamHandler is NOTSET by default, so it will let everything pass).
精彩评论