从python的日志记录器中删除处理程序

2024-05-19 12:04:17 发布

您现在位置:Python中文网/ 问答频道 /正文

我在玩Python的日志系统。我注意到在循环中从记录器对象中移除处理程序时出现了一个奇怪的行为。也就是说,我的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))

什么解释了这种行为?这是虫子还是我遗漏了什么?


Tags: instancedebug处理程序lenlogginghandlershandlerdbg
3条回答

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

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

我刚刚发现,您还可以在logging.ini文件中使用以下块执行此操作:

[logger_stpipe]
handlers=
propagate=1
qualname=stpipe

它基本上会停用给定记录器的所有处理程序。但这有点有限,因为你必须事先知道记录者的名字。

这不是特定于记录器的行为。永远不要对当前正在迭代的列表进行变异(插入/删除元素)。如果你需要,复印一份。在这种情况下,testLogger.handlers = []应该起作用。

相关问题 更多 >

    热门问题