我有三个Python模块:一个包含一个(抽象的)父类,另外两个包含实现此父类的类。父类有一些具体的和抽象的方法,它看起来像这样:
moduleA
:
from abc import ABC, abstractmethod
import logging
class Parent(ABC):
def __init__(self):
logger.info("Hello world from base class!")
def concreteMethod(self, something):
return something
@abstractmethod
def additionalMethod(self, something):
"""it needs to be implemented"""
moduleB
:
import logging
from moduleA import Parent
logger = logging.getLogger("b_logger")
fh = logging.FileHandler('b_logger.log')
fh.setLevel(logging.DEBUG)
logger.addHandler(fh)
class ChildB(Parent):
def __init__(self):
super().__init__()
def additionalMethod(self):
logger.info("Hello world from B")
moduleC
:
import logging
from moduleA import Parent
logger = logging.getLogger("c_logger")
fh = logging.FileHandler('c_logger.log')
fh.setLevel(logging.DEBUG)
logger.addHandler(fh)
class ChildC(Parent):
def __init__(self):
super().__init__()
def additionalMethod(self):
logger.info("Hello world from C")
现在,如果我决定跑步:
from moduleB import ChildB
from moduleC import ChildC
B = ChildB()
B.additionalMethod()
C = ChildC()
C.additionalMethod()
我想有两个日志文件,每个日志文件的父类一行,子类一行。
我的问题是,如何配置父类记录器以登录到子类的日志文件(而不是其自身)?
答案 0 :(得分:1)
如果要由子类确定记录器,则必须使记录器成为子类的属性。 ABC可以使用抽象属性记录此要求:
class Parent(ABC):
def __init__(self):
self.logger.info("Hello world from base class!")
@property
@abstractmethod
def logger(self):
"""A logger object (can be a class attribute) to log messages to."""
def concreteMethod(self, something):
return something
@abstractmethod
def additionalMethod(self, something):
"""it needs to be implemented"""
然后在子类上设置logger
属性。
如果您需要记录器成为全局模块,则名称logger
可能会使将同一对象作为类属性重用变得困难。您可以通过为类属性使用其他名称(而不是Parent.logger
或其他名称)或在模块中为记录器添加别名来解决此问题:
logger = b_logger = logging.getLogger("b_logger")
class ChildB(Parent):
logger = b_logger
def additionalMethod(self):
self.logger.info("Hello world from B")
上面的additionalMethod()
方法使用class属性,但是您当然也可以自由使用全局名称logger
或b_logger
。使用self.logger
将允许其他子类再次更改记录器引用。