【问题标题】:Logging from an abstract class从抽象类记录
【发布时间】:2018-10-03 11:53:20
【问题描述】:

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

我想要两个日志文件,每个文件都有一行来自父类,一个来自子类。

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

【问题讨论】:

  • 这不是一个真正的 ABC 问题;在这里使用抽象基类无关紧要。

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


【解决方案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() 方法使用了类属性,当然你也可以随意使用全局名称loggerb_logger。使用self.logger 将允许进一​​步的子类再次更改记录器引用。

【讨论】:

  • 谢谢,这对我有用!我是这样实现的:1. 在 Parent 中添加 @property @abstractmethod(就像你写的一样), 2. 在 Child 中将 logger 定义和初始化为 class 属性, 3. 在任何方法中我现在可以拨打这两个课程self.logger.info(...)
  • @machaerus:是的,直接从logging.getLogger() 调用设置logger 类属性也很好,它不必首先是模块级全局。我只是想强调一下这种情况,因为可能会发生命名冲突。
猜你喜欢
  • 2019-02-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多