从python的日志记录器中删除处理程序
我正在玩Python的日志记录系统。我注意到一个奇怪的行为,同时从循环中的Logger对象中移除处理程序。也就是说,我的for循环删除除一个处理程序之外的所有程序对.removeHandler
的额外呼叫会顺利移除最后一个处理程序。在通话过程中不会发出错误消息。从python的日志记录器中删除处理程序
这是测试代码:
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))
这个行为的解释是什么?这是一个错误还是我错过了什么?
这不是特定于记录器的行为。 从不突变(插入/移除元素)您当前正在迭代的列表。如果您需要,请复印一份。在这种情况下,testLogger.handlers = []
应该做的伎俩。
呵呵呵:我错过了设置的明显的解决方案列表到[]。我想我需要更多的咖啡 –
如果你不想将它们全部删除(感谢the tip @CatPlusPlus):
testLogger.handlers = [
h for h in testLogger.handlers if not isinstance(h, logging.StreamHandler)]
对不起,我发现这并没有work.for isinstance不能用来判断处理程序的类型 –
@fat_cheng为什么isinstance不能用于这个目的?我自己似乎在使用这个答案中的建议时没有问题。 – AlanSE
我在Ubuntu 16.04中使用python3。我使用'if(type(h)== logging.StreamHandler)]'代替。 –
'在列表H(testLogger.handlers)' – sherpya