鉴于这一点 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 构造函数
我究竟做错了什么?
当您调用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的自定义。