В файле, где я определяю класс mixin, как мне использовать регистратор из файла, в котором используется mixin?

#python #class #logging #mixins #superclass

#python #класс #ведение журнала #mixins #суперкласс

Вопрос:

Я абстрагируюсь от повторяющегося фрагмента кода, в котором я настраиваю регистратор во многих классах.

Я хотел бы иметь класс, в котором mixin позволяет мне либо создавать экземпляр класса с помощью объекта logger, либо использовать модуль по умолчанию в модуле этого класса.

Я бы использовал его следующим образом:

 import logging
from .mixin import LoggerMixin


resource_module_logger = logging.getLogger(__name__)


class MyResource(LoggerMixin):
    """ Instantiate this class to do something.

    If instantiated with a custom logger, then all log outputs will go to that. Otherwise, they'll go to resource_module_logger

    ```
    MyResource().do_something()  # Does something while logging to resource module logger.
    MyResource(logger=logging.getLogger("specific"))  # does something while logging to a specific logger.
    ```
    """

    def do_something(self):
        self.logger.info("This message will go to the default module level logger, unless a custom logger was specified at instantiation")
  

Пока что у меня есть mixin:

 import logging


this_is_not_the_logger_im_looking_for = logging.getLogger(__name__)


class LoggerMixin:

    def __init__(self, *args, logger=None, **kwargs):

        self._logger = logger
        super().__init__(*args, **kwargs)

    @property
    def logger(self):
        # How do I get the resource module logger for the MyResource class which this is mixed into???
        resource_module_logger = ?????????????
        return self._logger or resource_module_logger
  

Вопрос
Возможно ли получить этот регистратор из mixin и, следовательно, полностью абстрагироваться от него (и если да, то как?) или мне нужно переопределить logger свойство для каждого класса?

Ответ №1:

Вместо того, чтобы создавать экземпляр глобального в модуле и затем пытаться получить к нему доступ, вы могли бы просто использовать getLogger непосредственно для извлечения регистратора на основе имени модуля. Кроме того, я бы просто выполнил значение по умолчанию один раз в __init__ вместо каждого поиска в свойстве:

 self._logger = logger or logging.getLogger(self.__class__.__module__)
  

Редактировать — включить полное решение

Полный mixin, loggable.py , тогда был бы:

 import logging


class Loggable:
    """ Mixin to allow instantiation of a class with a logger, or by default use the module logger from that class

    ```
    class MyResource(Logged):
        def do_something(self):
            self.logger.info('write to a logger')

    MyResource().do_something()  # Log statements go to the default logger for the module in which MyResource is a member
    MyResource(logger=logging.getLogger("specific"))  # Log statements go to the specific logger.
    ```
    """

    def __init__(self, *args, logger=None, **kwargs):
        super().__init__(*args, **kwargs)
        self._logger = logger or logging.getLogger(self.__class__.__module__)

    @property
    def logger(self):
        return self._logger