日志设置级别,如何工作
在日志记录的使用说明中,有一个例子:
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)
为什么我需要把日志级别设置为logging.DEBUG
两次,分别对Logger
和StreamHandler
?
我明白ch.setLevel(logging.DEBUG)
是为流处理器设置调试级别。但是,设置Logger的级别有什么作用?这个级别在哪里体现呢?
如果我把级别改成,比如说INFO
,无论是对Logger
还是StreamHandler
,我得到的控制台输出都是一样的。
也就是说:
...........
logger.setLevel(logging.INFO)
............
ch.setLevel(logging.DEBUG)
在控制台上输出和
...........
logger.setLevel(logging.DEBUG)
............
ch.setLevel(logging.INFO)
是一样的。
3 个回答
我觉得理解日志工作原理时,可以考虑以下三个主要点:
你可以创建一个Logger对象的层级结构。每个Logger一开始都没有设置级别(级别是NOTSET)。一个Logger对象的有效级别是指在层级结构中向上查找时,第一个被设置的级别(如果没有设置过,可能是NOTSET)。
Logger的有效级别仅用于判断是否要处理直接发给这个logger的消息。
这个处理过程首先是把消息传给这个Logger的处理器,然后(根据propagate标志的值)把消息传给所有祖先Logger的处理器,一直到最顶层,而不考虑这些Logger的实际级别。
针对你的问题,在那个例子中你不需要设置两次。只在Logger中设置为DEBUG就足够了,这样直接发给你的Logger实例的日志消息就能顺利到达控制台(因为新建的StreamHandler默认级别是NOTSET,所以它会放行所有消息)。
为什么我需要把日志级别设置为 logging.DEBUG 两次,一个是给 logger,另一个是给 streamhandler。我明白 ch.setLevel(logging.DEBUG) 是为流处理器设置调试级别。那么设置 logger 的级别有什么效果呢?这个级别又在哪里体现呢?
文档中有说明:
“setLevel() 方法和 logger 对象一样,指定了将被发送到相应目的地的最低严重性级别。为什么有两个 setLevel() 方法?在 logger 中设置的级别决定了它会把哪些严重性级别的消息传递给它的处理器。而在每个处理器中设置的级别决定了那个处理器会发送哪些消息。”
可以查看处理器部分:http://docs.python.org/2.7/howto/logging.html#logging-advanced-tutorial
这个设置是为了让你更灵活地调整(你可以有多个处理器,每个处理器可以设置不同的级别)——你可以放心地不为处理器设置级别,这样它就会处理所有消息(也就是所谓的NOTSET级别),而把级别过滤的工作留给记录器来做。
记录器是第一个根据级别来过滤消息的——如果你把记录器设置为INFO,而所有处理器都设置为DEBUG,你依然收不到DEBUG消息,因为这些消息会被记录器自己拒绝。如果你把记录器设置为DEBUG,但所有处理器都设置为INFO,你也收不到任何DEBUG消息——因为虽然记录器说“好的,处理这个”,但处理器却拒绝了它(DEBUG < INFO)。