Как установить обработчик для всех регистраторов в проекте? - PullRequest
1 голос
/ 16 февраля 2020

Я хочу использовать регистратор памяти в моем проекте. Он отслеживает последние n записей журнала. Пример минимального основного файла выглядит следующим образом:

import sys
import logging
from logging import StreamHandler
from test_module import do_stuff

logger = logging.getLogger(__name__)


class MemoryHandler(StreamHandler):
    def __init__(self, n_logs: int):

        StreamHandler.__init__(self)
        self.n_logs = n_logs
        self.my_records = []

    def emit(self, record):
        self.my_records.append(self.format(record))
        self.my_records = self.my_records[-self.n_logs:]

    def to_string(self):
        return '\n'.join(self.my_records)


if __name__ == '__main__':
    logging.basicConfig(stream=sys.stdout, level=logging.INFO)

    mem_handler = MemoryHandler(n_logs=10)
    logger.addHandler(mem_handler)
    logger.info('hello')
    do_stuff()

    print(mem_handler.to_string())

Тестовый модуль, из которого я импортирую do_stuff, выглядит следующим образом:

import logging

logger = logging.getLogger(__name__)


def do_stuff():
    logger.info('doing stuff')

Когда я запускаю основную функцию, два оператора журнала появляются. Один из основного, другой - из «делать вещи», но регистратор памяти получает только «привет», а не «делает вещи»:

INFO:__main__:hello
INFO:test_module:doing stuff
hello

Я предполагаю, что это потому, что mem_handler не добавляется в регистратор test_module , Я могу это исправить, добавив mem_handler явно:

logging.getLogger('test_module').addHandler(mem_handler)

Но в целом я не хочу перечислять все модули и добавлять mem_handler вручную. Как я могу добавить mem_handler ко всем регистраторам в моем проекте?

1 Ответ

2 голосов
/ 16 февраля 2020

Система ведения журнала Python является федеративной. Это означает, что существует древовидная структура, похожая на структуру пакета. Эта структура работает по имени регистратора, а уровни разделены точками.

Если вы используете модуль __name__ для получения регистратора, он будет эквивалентен пунктирному имени пакета. например:

package.subpackage.module

В этой объединенной системе сообщение отправляется в структуру регистраторов (если только один из регистраторов не настроен явно с propagate=False).

Итак, лучший способ добавить обработчик - это добавить его в регистратор root в верхней части структуры и убедиться, что все регистраторы ниже распространяются.

Вы можете получить регистратор root с logging.getLogger() (без имени ), а затем добавьте обработчики или другую конфигурацию, как вам нравится.

...