Ведение журнала из абстрактного класса - PullRequest
0 голосов
/ 03 октября 2018

У меня есть три модуля 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 голосов
/ 03 октября 2018

Если вы хотите, чтобы подкласс определял регистратор, то вам нужно сделать регистратор атрибутом подклассов.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()Приведенный выше метод использует атрибут класса, но вы, конечно, можете использовать глобальные имена logger или b_logger.Использование self.logger позволит другим подклассам снова изменить ссылку на регистратор.

...