Сообщения журнала, появляющиеся дважды в журнале Python
Я использую ведение журнала Python, и по какой-то причине все мои сообщения появляются дважды.
У меня есть модуль для настройки ведения журнала:
# BUG: It outputting logging messages twice - not sure why - it 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)
И почему-то все сообщения появляются дважды. Я прокомментировал один из обработчиков потоков, все тот же. Немного странно, не знаю, почему это происходит... lol. Предполагая, что я пропустил что-то очевидное.
Cheers,
Виктор
Ответы
Ответ 1
Вы вызываете configure_logging
дважды (возможно, в __init__
метод Boy
): getLogger
вернет тот же объект, но addHandler
не проверяет, был ли аналогичный обработчик уже добавлен в регистратор.
Попробуйте трассировать вызовы этого метода и устранить один из них. Или настройте флаг logging_initialized
, инициализированный на False
в методе __init__
Boy
и измените configure_logging
, чтобы ничего не делать, если logging_initialized
is 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)
Ответ 2
Обработчик добавляется каждый раз, когда вы вызываете извне. Попробуйте удалить обработчик после завершения работы:
self.logger.removeHandler(ch)
Ответ 3
Я новичок в python, но для меня это работало (Python 2.7)
while logger.handlers:
logger.handlers.pop()
Ответ 4
Если вы видите эту проблему, и вы не добавляете обработчик дважды, то см. ответ abarnert здесь
Из docs:
Примечание. Если вы прикрепляете обработчик к регистратору и один или несколько его предков, он может издавать одну и ту же запись несколько раз. В общем, вы не нужно прикреплять обработчик к нескольким регистраторам - если вы просто присоедините его к соответствующему регистратору, который является самым высоким в иерархии регистратора, тогда он увидит все события, зарегистрированные всем потомком loggers, при условии, что их параметр распространения остается равным True. общий сценарий заключается в том, чтобы привязывать обработчики только к корневому журналу и пусть пропаганда позаботится об остальном.
Итак, если вы хотите, чтобы пользовательский обработчик "test", и вы не хотите, чтобы его сообщения также поступали в обработчик root, ответ прост: отключите его флаг распространения:
logger.propagate = False