从抽象类记录

时间:2018-10-03 11:53:20

标签: python python-3.x oop logging python-3.6

我有三个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()

我想有两个日志文件,每个日志文件的父类一行,子类一行。

我的问题是,如何配置父类记录器以登录到子类的日志文件(而不是其自身)?

1 个答案:

答案 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属性,但是您当然也可以自由使用全局名称loggerb_logger。使用self.logger将允许其他子类再次更改记录器引用。