Python日志消息重复出现
我在用Python的日志功能,但不知道为什么,我的所有信息都出现了两次。
我有一个模块用来设置日志:
# BUG: It's outputting logging messages twice - not sure why - it's not the propagate setting.
def configure_logging(self, logging_file):
self.logger = logging.getLogger("my_logger")
self.logger.setLevel(logging.DEBUG)
self.logger.propagate = 0
# Format for our loglines
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
# Setup console logging
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
ch.setFormatter(formatter)
self.logger.addHandler(ch)
# Setup file logging as well
fh = logging.FileHandler(LOG_FILENAME)
fh.setLevel(logging.DEBUG)
fh.setFormatter(formatter)
self.logger.addHandler(fh)
之后,我调用这个方法来配置日志:
if __name__ == '__main__':
tom = Boy()
tom.configure_logging(LOG_FILENAME)
tom.buy_ham()
然后在比如说,buy_ham模块里,我会调用:
self.logger.info('Successfully able to write to %s' % path)
但不知道为什么,所有的信息都出现了两次。我把其中一个流处理器注释掉了,结果还是一样。这个情况有点奇怪,我不太明白为什么会这样。我想我可能漏掉了什么明显的东西。
16 个回答
我还是个Python新手,不过这个方法对我来说好像有效(Python 2.7)
while logger.handlers:
logger.handlers.pop()
如果你遇到这个问题,而且你确认没有重复添加处理器,那么可以看看abarnert的回答,在这里。
根据文档:
注意:如果你把一个处理器附加到一个记录器上,同时也附加到它的一个或多个父记录器上,那么它可能会多次输出同样的记录。一般来说,你不需要把处理器附加到多个记录器上——只要把它附加到层级中最高的那个记录器上,它就能看到所有子记录器记录的事件,只要它们的传播设置保持为True。一个常见的做法是只把处理器附加到根记录器上,然后让传播处理其余的事情。
所以,如果你想在“test”上使用一个自定义处理器,并且不想让它的消息也发送到根处理器,那么解决办法很简单:关闭它的propagate
标志:
logger.propagate = False
你在调用 configure_logging
这个方法两次(可能是在 Boy
的 __init__
方法里)。虽然 getLogger
会返回同一个对象,但 addHandler
不会检查这个日志记录器是否已经添加了相似的处理器。
你可以试着追踪一下这个方法的调用,看看能不能去掉其中一个。或者在 Boy
的 __init__
方法里设置一个标志 logging_initialized
,初始值为 False
,然后修改 configure_logging
方法,让它在 logging_initialized
为 True
时什么都不做,并在你初始化日志记录器后把它设置为 True
。
如果你的程序创建了多个 Boy
实例,你需要改变一下处理方式,使用一个全局的 configure_logging
函数来添加处理器,而 Boy.configure_logging
方法只负责初始化 self.logger
属性。
解决这个问题的另一种方法是检查你的日志记录器的处理器属性:
logger = logging.getLogger('my_logger')
if not logger.handlers:
# create the handlers and call logger.addHandler(logging_handler)