Модуль ведения журнала Python: пользовательские регистраторы

Я пытался создать пользовательский атрибут для ведения журнала (имя класса вызывающего абонента,имя модуля и т. д.) и застрял со странным исключением, сообщающим мне, что экземпляр LogRecord, созданный в процессе, не имел необходимых атрибутов. После небольшого тестирования я закончил с этим:

import logging

class MyLogger(logging.getLoggerClass()):
    value = None

logging.setLoggerClass(MyLogger)

loggers = [
    logging.getLogger(),
    logging.getLogger(""),
    logging.getLogger("Name")
]

for logger in loggers:
    print(isinstance(logger, MyLogger), hasattr(logger, "value"))

этот, казалось бы, правильный кусок дает код:

False False
False False
True True

баг или фича?

2 ответов


глядя на исходный код, мы можем увидеть следующее:

root = RootLogger(WARNING)
def getLogger(name=None):
    if name:
        return Logger.manager.getLogger(name)
    else:
        return root

то есть, корневой логгер создается по умолчанию при импорте модуля. Следовательно, каждый раз, когда вы ищете root looger (передавая ложное значение, такое как пустая строка), вы получите logging.RootLogger объект независимо от любого вызова logging.setLoggerClass.

Что касается используемого класса logger, мы можем видеть:

_loggerClass = None
def setLoggerClass(klass):
    ...
    _loggerClass = klass

это означает, что глобальная переменная содержит класс logger использовать в будущем.

в дополнение к этому, глядя на logging.Manager (используется logging.getLogger), мы можем видеть это:

def getLogger(self, name):
    ...
            rv = (self.loggerClass or _loggerClass)(name)

то есть, если self.loggerClass не установлен (который не будет, если вы явно не установили его), используется класс из глобальной переменной.

следовательно, это функция. Корневой регистратор всегда является logging.RootLogger "объект" и другие объекты регистратор создаются на основе конфигурации в то время.


logging.getLogger() и logging.getLogger("") не возвратить MyLogger потому что они возвращают корневой регистратор иерархии ведения журнала, как описано в ведение документации:

ведение журнала.getLogger([имя])

возврат регистратора с указанным именем или, если имя не указано, возврат регистратора, который является корневым регистратором иерархии.

таким образом, как вы настроили регистратор:

>>> logging.getLogger()
<logging.RootLogger object at 0x7d9450>
>>> logging.getLogger("foo")
<test3.MyLogger object at 0x76d9f0>

Я не думаю, что это связанные с KeyError вы начали свой пост. Вы должны опубликовать код, который вызвал это исключение (test.py).