Удаление обработчиков из логгеров python - PullRequest
44 голосов
/ 20 сентября 2011

Я играю с системой регистрации Python. Я заметил странное поведение при удалении обработчиков из объекта Logger в цикле. А именно, цикл for удаляет все, кроме одного обработчика. Дополнительный вызов .removeHandler плавно удаляет последний обработчик. Во время разговора сообщений об ошибках не выдается.

Это тестовый код:

import logging
import sys
logging.basicConfig()
dbg = logging.getLogger('dbg')
dbg.setLevel(logging.DEBUG)

testLogger = logging.getLogger('mylogger')
sh = logging.StreamHandler(sys.stdout)
fh = logging.FileHandler('mylogfile.log')
dbg.debug('before adding handlers: %d handlers'%len(testLogger.handlers))
testLogger.addHandler(fh)
testLogger.addHandler(sh)

dbg.debug('before removing. %d handlers: %s'%(len(testLogger.handlers), 
                                              str(testLogger.handlers)))
for h in testLogger.handlers:
    dbg.debug('removing handler %s'%str(h))
    testLogger.removeHandler(h)
    dbg.debug('%d more to go'%len(testLogger.handlers))

#HERE I EXPECT THAT NO HANDLER WILL REMAIN    
dbg.debug('after removing: %d handlers: %s'%(len(testLogger.handlers), 
                                              str(testLogger.handlers)))
if len(testLogger.handlers) > 0:
    #Why is this happening?
    testLogger.removeHandler(testLogger.handlers[0])
dbg.debug('after manually removing the last handler: %d handlers'%len(testLogger.handlers))    

Я ожидаю, что в конце цикла никакие обработчики не останутся в объекте testLogger, однако последний вызов .removeHandler, по-видимому, терпит неудачу, как видно из вывода ниже. тем не менее дополнительный вызов этой функции удаляет обработчик, как и ожидалось. Вот вывод:

DEBUG:dbg:before adding handlers: 0 handlers
DEBUG:dbg:before removing. 2 handlers: [<logging.FileHandler instance at 0x021263F0>, <logging.StreamHandler instance at 0x021262B0>]
DEBUG:dbg:removing handler <logging.FileHandler instance at 0x021263F0>
DEBUG:dbg:1 more to go
DEBUG:dbg:after removing: 1 handlers: [<logging.StreamHandler instance at 0x021262B0>]
DEBUG:dbg:after manually removing the last handler: 0 handlers

Более интересно, если я заменю исходный цикл следующим, цикл работает как положено, и в конце цикла в объекте testLogger не осталось обработчиков. Вот модифицированный цикл:

while len(testLogger.handlers) > 0:
    h = testLogger.handlers[0]
    dbg.debug('removing handler %s'%str(h))
    testLogger.removeHandler(h)
    dbg.debug('%d more to go'%len(testLogger.handlers))

Чем объясняется такое поведение? Это ошибка или я что-то упустил?

Ответы [ 3 ]

90 голосов
/ 20 сентября 2011

Это не специфичное для логгера поведение. Никогда не изменяет (вставляет / удаляет элементы) список, который вы сейчас просматриваете. Если вам нужно, сделайте копию. В этом случае testLogger.handlers = [] должен добиться цели.

10 голосов
/ 29 марта 2016

Если вы не хотите удалять их все (спасибо за подсказку @ CatPlusPlus ):

testLogger.handlers = [
    h for h in testLogger.handlers if not isinstance(h, logging.StreamHandler)]
1 голос
/ 16 апреля 2018

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

[logger_stpipe]
handlers=
propagate=1
qualname=stpipe

Это в основном деактивирует все обработчики для данного регистратора. Но это несколько ограничено, потому что вы должны знать имя Регистратора заранее.

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