Я использую ведение журнала 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)
И почему-то все сообщения появляются дважды. Я закомментировал один из обработчиков потока, все то же самое. Немного странный, не знаю, почему это происходит ... лол. Предполагая, что я упустил что-то очевидное.
Ура, Виктор
configure_logging()
не вызывается дважды (например, тоже из конструктора)? Создан только один экземпляр Boy ()?self.logger.handlers = [ch]
вместо этого решило бы эту проблему, хотя было бы лучше просто убедиться, что вы не запускаете этот код дважды, например, используяif not self.logger
в начале.Ответы:
Вы вызываете
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
переменная была не той, которая была создана из одного из моих классов, аlogger
переменной, присутствующей в кеше Python3 , и обработчик добавлялся каждые 60 секунд настроенным мной AppScheduler. Итак, этоif not logger.handlers
довольно разумный способ избежать подобных явлений. Спасибо за решение, товарищ :)!Если вы столкнулись с этой проблемой и не добавляете обработчик дважды, см. Ответ abarnert здесь.
Из документов :
Итак, если вам нужен специальный обработчик для «test», и вы не хотите, чтобы его сообщения также передавались корневому обработчику, ответ прост: отключите его
propagate
флаг:источник
Обработчик добавляется каждый раз, когда вы звоните извне. Попробуйте удалить обработчик после завершения работы:
источник
logger.handlers.pop()
в Python 2.7, помогаетЯ новичок в Python, но, похоже, это сработало для меня (Python 2.7)
источник
В моем случае я бы установил
logger.propagate = False
предотвращение двойной печати.В приведенном ниже коде, если вы удалите,
logger.propagate = False
вы увидите двойную печать.источник
logger.propagate = False
было решением для предотвращения двойного входа в приложение Flask, размещенное в Waitress, при входе вapp.logger
экземпляр Flask .Обращение к
logging.debug()
вызовам,logging.basicConfig()
если не установлены корневые обработчики. Это происходило со мной в тестовой среде, где я не мог контролировать порядок запуска тестовых примеров. Мой код инициализации устанавливал второй. По умолчанию используется logging.BASIC_FORMAT, который мне не нужен.источник
Похоже, что если вы выводите что-то в логгер (случайно), а потом настраиваете, то уже поздно. Например, в моем коде у меня было
Я бы получил что-то вроде (игнорируя параметры формата)
и все было дважды записано на стандартный вывод. Я считаю, что это потому, что первый вызов
logging.warning
автоматически создает новый обработчик, а затем я явно добавил еще один обработчик. Проблема исчезла, когда я удалил случайный первыйlogging.warning
звонок.источник
У меня была странная ситуация, когда журналы консоли удваивались, а журналы файлов - нет. После тонны рытья я понял это.
Имейте в виду, что сторонние пакеты могут регистрировать регистраторы. Это то, чего нужно остерегаться (и в некоторых случаях это невозможно предотвратить). Во многих случаях сторонний код проверяет, существуют ли какие-либо существующие обработчики корневого регистратора; а если нет - регистрируют новый обработчик консоли.
Моим решением было зарегистрировать мой логгер консоли на корневом уровне:
источник