从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)) 

这个行为的解释是什么?这是一个错误还是我错过了什么?

+1

'在列表H(testLogger.handlers)' – sherpya

这不是特定于记录器的行为。 从不突变(插入/移除元素)您当前正在迭代的列表。如果您需要,请复印一份。在这种情况下,testLogger.handlers = []应该做的伎俩。

+4

呵呵呵:我错过了设置的明显的解决方案列表到[]。我想我需要更多的咖啡 –

如果你不想将它们全部删除(感谢the tip @CatPlusPlus):

testLogger.handlers = [ 
    h for h in testLogger.handlers if not isinstance(h, logging.StreamHandler)] 
+0

对不起,我发现这并没有work.for isinstance不能用来判断处理程序的类型 –

+1

@fat_cheng为什么isinstance不能用于这个目的?我自己似乎在使用这个答案中的建议时没有问题。 – AlanSE

+0

我在Ubuntu 16.04中使用python3。我使用'if(type(h)== logging.StreamHandler)]'代替。 –