Python Logging模块:自定义记录器

时间:2012-02-16 18:50:39

标签: python logging

我试图创建一个用于记录的自定义属性(调用者的类名,模块名称等),并且遇到一个奇怪的异常,告诉我在进程中创建的LogRecord实例没有必要的属性。经过一些测试后,我最终得到了这个:

import logging

class MyLogger(logging.getLoggerClass()):
    value = None

logging.setLoggerClass(MyLogger)

loggers = [
    logging.getLogger(),
    logging.getLogger(""),
    logging.getLogger("Name")
]

for logger in loggers:
    print(isinstance(logger, MyLogger), hasattr(logger, "value"))

这段看似正确的代码产生了:

False False
False False
True True

错误或功能?

2 个答案:

答案 0 :(得分:6)

查看源代码,我们可以看到以下内容:

root = RootLogger(WARNING)
def getLogger(name=None):
    if name:
        return Logger.manager.getLogger(name)
    else:
        return root

也就是说,导入模块时默认会创建根记录器。因此,每次查找根目录(传递假值,例如空字符串)时,无论是否调用logging.RootLogger,您都将获得logging.setLoggerClass个对象。

关于正在使用的记录器类,我们可以看到:

_loggerClass = None
def setLoggerClass(klass):
    ...
    _loggerClass = klass

这意味着全局变量保存将来使用的记录器类。

除此之外,查看logging.Manager(由logging.getLogger使用),我们可以看到:

def getLogger(self, name):
    ...
            rv = (self.loggerClass or _loggerClass)(name)

也就是说,如果没有设置self.loggerClass(除非你明确设置它,否则不会这样),使用全局变量中的类。

因此,这是一个功能。根记录器始终是logging.RootLogger对象,其他记录器对象是根据当时的配置创建的。

答案 1 :(得分:2)

logging.getLogger()logging.getLogger("")不会返回MyLogger,因为它们会返回日志记录层次结构的根记录器,如logging documentation中所述:

  

logging.getLogger([名称])

     

返回具有指定名称的记录器,或者,如果未指定名称,则返回记录器,该记录器是层次结构的根记录器。

因此,正如您设置了记录器:

>>> logging.getLogger()
<logging.RootLogger object at 0x7d9450>
>>> logging.getLogger("foo")
<test3.MyLogger object at 0x76d9f0>

我认为这与您发布帖子的KeyError无关。您应该发布导致该异常的代码(test.py)。