регистрировать сообщения, появляющиеся дважды с Python Logging - PullRequest
66 голосов
/ 18 июля 2011

Я использую логи Python, и по какой-то причине все мои сообщения появляются дважды.

У меня есть модуль для настройки ведения журнала:

# BUG: It's outputting logging messages twice - not sure why - it's not the propagate setting.
def configure_logging(self, logging_file):
    self.logger = logging.getLogger("my_logger")
    self.logger.setLevel(logging.DEBUG)
    self.logger.propagate = 0
    # Format for our loglines
    formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
    # Setup console logging
    ch = logging.StreamHandler()
    ch.setLevel(logging.DEBUG)
    ch.setFormatter(formatter)
    self.logger.addHandler(ch)
    # Setup file logging as well
    fh = logging.FileHandler(LOG_FILENAME)
    fh.setLevel(logging.DEBUG)
    fh.setFormatter(formatter)
    self.logger.addHandler(fh)

Позже я вызываю этот метод для настройки ведения журнала:

if __name__ == '__main__':
    tom = Boy()
    tom.configure_logging(LOG_FILENAME)
    tom.buy_ham()

А потом, скажем, модуль buy_ham, я бы позвонил:

self.logger.info('Successfully able to write to %s' % path)

И по какой-то причине все сообщения появляются дважды. Я закомментировал один из потоковых обработчиков, все то же самое. Немного странно, не уверен, почему это происходит ... смеется. Предполагая, что я пропустил что-то очевидное.

Cheers, Victor

Ответы [ 5 ]

95 голосов
/ 18 июля 2011

Вы вызываете configure_logging дважды (возможно, в методе __init__ из Boy): getLogger вернет тот же объект, но addHandler не проверяет, был ли уже добавлен аналогичный обработчик в регистратор.

Попробуйте отследить вызовы этого метода и исключить один из них. Или установите флаг logging_initialized, инициализированный на False в методе __init__ Boy, и измените configure_logging, чтобы он ничего не делал, если logging_initialized равен True, и установите его на True после того, как вы инициализировал регистратор

Если ваша программа создает несколько экземпляров Boy, вам придется изменить способ работы с помощью глобальной функции configure_logging, добавляющей обработчики, а метод Boy.configure_logging только инициализирует атрибут self.logger.

Еще один способ решить эту проблему - проверить атрибут handlers вашего логгера:

logger = logging.getLogger('my_logger')
if not logger.handlers:
    # create the handlers and call logger.addHandler(logging_handler)
8 голосов
/ 08 июня 2017

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

Из документов :

Примечание: если вы присоедините обработчик к логгеру и один или несколько его предки, он может испускать одну и ту же запись несколько раз. В общем ты не нужно подключать обработчик к нескольким регистраторам - если вы просто прикрепите его к соответствующему регистратору, который является самым высоким в иерархия регистратора, тогда он увидит все события, записанные всеми потомками регистраторы при условии, что для их параметра распространения установлено значение True. Обычный сценарий - подключить обработчики только к корневому логгеру и пусть распространение позаботится обо всем остальном.

Итак, если вам нужен пользовательский обработчик для «test», и вы не хотите, чтобы его сообщения также отправлялись в корневой обработчик, ответ прост: отключите его флаг распространения:

logger.propagate = False

6 голосов
/ 06 марта 2014

Обработчик добавляется каждый раз, когда вы звоните извне.Попробуйте удалить обработчик после завершения работы:

self.logger.removeHandler(ch)
5 голосов
/ 14 декабря 2016

Я новичок в Python, но мне показалось, что это работает (Python 2.7)

while logger.handlers:
     logger.handlers.pop()
0 голосов
/ 05 января 2019

Вызов logging.debug() вызывает logging.basicConfig(), если не установлены корневые обработчики.Это происходило для меня в тестовой среде, где я не мог контролировать порядок запуска тестовых случаев.Мой код инициализации устанавливал второй.По умолчанию используется logging.BASIC_FORMAT, который я не хотел.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...