Python Logging模块:自定义记录器

Pas*_*ist 8 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"))
Run Code Online (Sandbox Code Playgroud)

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

False False
False False
True True
Run Code Online (Sandbox Code Playgroud)

错误或功能?

jco*_*ado 6

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

root = RootLogger(WARNING)
def getLogger(name=None):
    if name:
        return Logger.manager.getLogger(name)
    else:
        return root
Run Code Online (Sandbox Code Playgroud)

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

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

_loggerClass = None
def setLoggerClass(klass):
    ...
    _loggerClass = klass
Run Code Online (Sandbox Code Playgroud)

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

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

def getLogger(self, name):
    ...
            rv = (self.loggerClass or _loggerClass)(name)
Run Code Online (Sandbox Code Playgroud)

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

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