Python日志记录模块多次打印行

Nik*_*ngh 11 python logging

我有以下代码:

import logging
class A(object):
    def __init__(self):
        self._l = self._get_logger()

    def _get_logger(self):
        loglevel = logging.INFO
        l = logging.getLogger(__name__)
        l.setLevel(logging.INFO)
        h = logging.StreamHandler()
        f = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
        h.setFormatter(f)
        l.addHandler(h)
        l.setLevel(loglevel)
        return l  

    def p(self, msg):
        self._l.info(msg)

for msg in ["hey", "there"]:
    a = A()
    a.p(msg)
Run Code Online (Sandbox Code Playgroud)

我得到的输出是:

2013-07-19 17:42:02,657 INFO hey
2013-07-19 17:42:02,657 INFO there
2013-07-19 17:42:02,657 INFO there
Run Code Online (Sandbox Code Playgroud)

为什么"那里"被打印两次?同样,如果我在循环中添加A类的另一个对象并打印一条消息,它将被打印三次.

文档说如果记录器的名称匹配,logging.getLogger()将始终返回相同的记录器实例.在这种情况下,名称确实匹配.它不应该返回相同的记录器实例吗?如果它实际上是这样做的,为什么消息会被多次打印?

fal*_*tru 18

logger创建一次,但创建了多个处理程序.

创建A一次.

a = A()
for msg in ["hey", "there"]:
    a.p(msg)
Run Code Online (Sandbox Code Playgroud)

或者改变_get_logger如下:

def _get_logger(self):
    loglevel = logging.INFO
    l = logging.getLogger(__name__)
    if not getattr(l, 'handler_set', None):
        l.setLevel(loglevel)
        h = logging.StreamHandler()
        f = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
        h.setFormatter(f)
        l.addHandler(h)
        l.setLevel(loglevel)
        l.handler_set = True
    return l  
Run Code Online (Sandbox Code Playgroud)

UPDATE

从Python 3.2开始,您可以使用它logging.Logger.hasHandlers来查看此记录器是否配置了任何处理程序.(感谢@toom)

def _get_logger(self):
    loglevel = logging.INFO
    l = logging.getLogger(__name__)
    if not l.hasHandlers():
        ...
    return l
Run Code Online (Sandbox Code Playgroud)

  • @NikhilSingh:`getLogger`每次都会返回相同的记录器,但是每次实例化`A`时,您都会在同一个记录器上调用`addHandler`。它将为您添加的每个处理程序打印一条消息。 (3认同)

San*_*nju 7

在我的例子中,root loggers处理程序也被调用,我所做的就是将propagatelogger实例的属性设置为False.

import logging
logger = logging.getLogger("MyLogger")

# stop propagting to root logger
logger.propagate = False

# other log configuration stuff
# ....
Run Code Online (Sandbox Code Playgroud)


too*_*oom 5

从 python 3.2 及更高版本开始:

考虑使用hasHandlers()来检查记录器是否有处理程序。

https://docs.python.org/3/library/logging.html#logging.Logger.hasHandlers