日志消息用Python日志logging出现两次

我正在使用Python日志logging,出于某种原因,我的所有消息都出现了两次。

我有一个模块来configuration日志logging:

# 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) 

之后,我调用这个方法来configuration日志logging:

 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) 

由于某种原因,所有的信息都出现了两次。 我注意到一个stream处理程序,仍然是一样的东西。 一个奇怪的位,不知道为什么这是发生…大声笑。 假设我错过了一些明显的东西。

干杯,维克多

你正在调用configure_logging两次(可能在Boy__init__方法中): getLogger将返回相同的对象,但getLogger不检查是否已经将类似的处理程序添加到logging器。

尝试跟踪调用该方法,并消除其中之一。 或者在Boy__init__方法中将logging_initialized标志初始化为False ,如果logging_initializedTrue ,则将configure_logging改为logging_initialized ,并在初始化logger后将其设置为True

如果程序创build了多个Boy实例,则必须通过添加处理程序的全局configure_logging函数来更改方式,而Boy.configure_logging方法只能初始化self.logger属性。

解决这个问题的另一种方法是检查logging器的处理程序属性:

 logger = logging.getLogger('my_logger') if not logger.handlers: # create the handlers and call logger.addHandler(logging_handler) 

每次你从外面打电话都会添加处理程序。 完成工作后,尝试删除处理程序:

 self.logger.removeHandler(ch) 

我是一个python新手,但这似乎适用于我(Python 2.7)

 while logger.handlers: logger.handlers.pop() 

如果你看到这个问题,而你没有两次添加处理程序,那么请参阅abarnert的答案

从文档 :

注意:如果将处理程序附加到logging器及其一个或多个其祖先,则可能会多次发出相同的logging。 一般来说,你不需要把一个处理程序附加到多个logging器上 – 如果你只是把它附加到logging器层次结构中最高的适当的logging器上,那么它将看到所有的后代logging器logging的所有事件,只要它们的传播设置被设置为True。 一个常见的情况是只将处理程序附加到根logging器,并让传播处理其余部分。

所以,如果你想在“testing”上使用一个自定义处理程序,并且你不想让它的消息也进入根处理程序,答案很简单:closures其传播标志:

logger.propagate = False