关于python:让父类使用子类记录器名称

Have Parent Class Use Child Class Logger Name

我正在尝试建立一些日志记录,但遇到了一个问题。每当子类使用父类函数时,将使用父类函数记录器名称而不是子类的记录器名称。

假设我有以下两个类:

父类:

1
2
3
4
5
6
import logging
logger = logging.getLogger('ParentClass')

class ParentClass:
    def __init___(self):
        logger.info('This is inside ParentClass')

子类:

1
2
3
4
5
6
import logging
logger = logging.getLogger('ChildClass')

class ChildClass(ParentClass):
    def foo(self):
        logger.info('This is inside ChildClass')

然后我运行以下脚本:

1
2
3
4
5
6
7
8
import logging
import ParentClass
import ChildClass

# Pretend I set up logging to"example.log"
foo1 = ParentClass.ParentClass()
foo2 = ChildClass.ChildClass()
foo2.foo()

我的日志文件最终看起来像:

1
2
3
INFO:ParentClass:This is inside ParentClass  #(<-- this comes from foo1 init)
INFO:ParentClass:This is inside ParentClass  #(<-- this comes from foo2 init)
INFO:ChildClass:This is inside ChildClass    #(<-- this comes from foo2 foo)

我要找的是childclass的初始化调用,以便在childclass logger下登录,如下所示:

1
2
3
INFO:ParentClass:This is inside ParentClass  #(<-- this comes from foo1 init)
INFO:ChildClass:This is inside ParentClass   #(<-- this comes from foo2 init)
INFO:ChildClass:This is inside ChildClass    #(<-- this comes from foo2 foo)

是否仍要在不将要使用的记录器的名称传递给ParentClass的情况下执行此操作?


您的每个类都使用自己的记录器来记录自己的代码,因为您是通过两个模块中的每个模块中的一个全局变量访问记录器的。如果希望将记录器绑定到类而不是模块,请尝试将其设置为类变量,并通过self访问它:

1
2
3
4
5
6
7
8
9
class ParentClass:
    logger = logging.getLogger('ParentClass') # class variable
    def __init___(self):
        self.logger.info('This is inside ParentClass')

class ChildClass(ParentClass):
    logger = logging.getLogger('ChildClass') # override parent class variable
    def foo(self):
        self.logger.info('This is inside ChildClass')


基于Sureshvv的职位,我发现将其放入父类的__init__方法中很有帮助:

1
self.log = logging.getLogger(self.__class__.__name__)

然后,子类可以使用self.log进行日志记录,并使用日志格式的%(name)s令牌正确显示子类名称,而不是父类的类名(如果将__name__传递给getLogger()会发生这种情况)。


您需要使logger成为类的属性。现在看来,ParentClass只能调用其模块中定义的记录器:它无法访问ChildClass中的记录器(除非parentclass模块导入子类并显式调用ChildClass.logger)。

相反,对parentClass模块执行此操作:

1
2
3
4
5
6
7
import logging

class ParentClass:
    logger = logging.getLogger('ParentClass')

    def __init___(self):
        self.logger.info('This is inside ParentClass')

儿童班:

1
2
3
4
5
6
7
8
import logging
import ParentClass    # I assume you do this, too

class ChildClass(ParentClass):
    logger = logging.getLogger('ChildClass')

    def foo(self):
        self.logger.info('This is inside ChildClass')


你可以:

1
use self.__class__ as argument to getLogger().