Python 3.7 logging.setLoggerClass() 不是

Gra*_*meU 2 python logging

鉴于这一点 Python:

logging.setLoggerClass(MyLogger)    
logger = logging.getLogger()    
print(type(logger))
Run Code Online (Sandbox Code Playgroud)

...我相信是一个正确实现的 MyLogger 类:

class MyLogger(logging.getLoggerClass()):
    def __init__(self, name: str=os.path.basename(__file__)) -> None:
        logging.Logger.__init__(self, name=name)
Run Code Online (Sandbox Code Playgroud)

我希望 GetLogger 返回 MyLogger 的一个实例,但它没有:

<class 'logging.RootLogger'>
Run Code Online (Sandbox Code Playgroud)

没有错误或警告。当我调用 logging.getLogger() 时,似乎也从未调用过 MyLogger 构造函数

我究竟做错了什么?

wim*_*wim 5

当您调用setLoggerClass(...). 根记录器已经实例化,它是在执行时创建的import logging,并且作为一个RootLogger实例存在于日志模块的命名空间中。该getLogger()调用只是返回现有实例。

但是,您随后创建的任何其他记录器,例如logging.getLogger('mylogger'),都将是您的子类的实例。通常,您将在模块的顶部放置它:

log = logging.getLogger(__name__)
Run Code Online (Sandbox Code Playgroud)

并且此日志将通过一个MyLogger实例。

现在,您不应该真正关心根记录器是什么类,因为无论如何您都不希望它处理事件。但是,由于这是 Python,如果我们真的愿意,我们可以射击我们自己的祖父母,因此可以完全相同地改变根记录器的类型:

>>> root = logging.getLogger()
>>> root.__class__ = MyLogger
>>> root
<MyLogger root (WARNING)>
Run Code Online (Sandbox Code Playgroud)

根记录器与任何其他记录器没有什么不同,只是它必须具有日志记录级别。如果您在实现时遵守Liskov 替换原则MyLogger,这应该可以正常工作 - 到达根记录器的任何事件都可以使用MyLogger的自定义。