Как использовать разные форматеры с одним и тем же обработчиком журналирования в python - PullRequest
18 голосов
/ 16 ноября 2009

Можно ли войти в один пункт назначения (т. Е. Используя один FileHandler) с несколькими регистраторами (т.е. logging.getLogger("base.foo") и logging.getLogger("base.bar")) и использовать разные форматеры для каждого из регистраторов.

Насколько я понимаю, можно назначить только один форматер для каждого дескриптора. Может быть, можно связать средство форматирования с регистратором, а не с обработчиком?

Ответы [ 2 ]

16 голосов
/ 16 ноября 2009

Легко отправить в разные форматеры на основе record.name. Ниже приведен пример кода для проверки концепции:

import logging


class DispatchingFormatter:

    def __init__(self, formatters, default_formatter):
        self._formatters = formatters
        self._default_formatter = default_formatter

    def format(self, record):
        formatter = self._formatters.get(record.name, self._default_formatter)
        return formatter.format(record)


handler = logging.StreamHandler()
handler.setFormatter(DispatchingFormatter({
        'base.foo': logging.Formatter('FOO: %(message)s'),
        'base.bar': logging.Formatter('BAR: %(message)s'),
    },
    logging.Formatter('%(message)s'),
))
logging.getLogger().addHandler(handler)

logging.getLogger('base.foo').error('Log from foo')
logging.getLogger('base.bar').error('Log from bar')
logging.getLogger('base.baz').error('Log from baz')

Другой способ - открыть файл вручную и создать из него два потоковых обработчика с разными форматерами.

1 голос
/ 06 января 2016

Небольшое исправление к отличному решению Дениса.

Система имен журналирования на основе иерархической структуры:

name потенциально представляет собой иерархическое значение, разделенное точками, например foo.bar.baz (хотя это также может быть просто foo, например). Регистраторы, которые находятся ниже в иерархическом списке, являются потомками регистраторы выше в списке. Например, дан логгер с именем foo, регистраторы с именами foo.bar, foo.bar.baz и foo.bam все потомки foo.

Например, когда вы setLevel () для какого-либо регистратора, этот уровень также будет применяться к дочерним регистраторам. Вот почему вы можете захотеть, чтобы ваш форматтер использовался для логгеров, а также для дочерних логгеров. Например, 'one.two' форматер должен также применяться к 'one.two.three' регистратору (если не установлен форматер для 'one.two.three') Вот версия DispatchingFormatter, которая делает работу (код Python 3):

class DispatchingFormatter:
    """Dispatch formatter for logger and it's sub logger."""
    def __init__(self, formatters, default_formatter):
        self._formatters = formatters
        self._default_formatter = default_formatter

    def format(self, record):
        # Search from record's logger up to it's parents:
        logger = logging.getLogger(record.name)
        while logger:
            # Check if suitable formatter for current logger exists:
            if logger.name in self._formatters:
                formatter = self._formatters[logger.name]
                break
            else:
                logger = logger.parent
        else:
            # If no formatter found, just use default:
            formatter = self._default_formatter
        return formatter.format(record)

Пример:

handler = logging.StreamHandler()
handler.setFormatter(DispatchingFormatter({
        'one': logging.Formatter('%(message)s -> one'),
        'one.two': logging.Formatter('%(message)s -> one.two'),
    },
    logging.Formatter('%(message)s -> <default>'),
))
logging.getLogger().addHandler(handler)

print('Logger used -> formatter used:')
logging.getLogger('one').error('one')
logging.getLogger('one.two').error('one.two')
logging.getLogger('one.two.three').error('one.two.three')  # parent formatter 'one.two' will be used here
logging.getLogger('other').error('other')

# OUTPUT:
# Logger used -> formatter used:
# one -> one
# one.two -> one.two
# one.two.three -> one.two
# other -> <default>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...