从python中删除处理程序';伐木工人

从python中删除处理程序';伐木工人,python,logging,Python,Logging,我正在玩Python的日志系统。我注意到在循环中从记录器对象中删除处理程序时出现了一种奇怪的行为。也就是说,我的for循环删除除一个处理程序之外的所有处理程序。对.removeHandler的附加调用将平滑地删除最后一个处理程序。在呼叫过程中不会发出错误消息 这是测试代码: import logging import sys logging.basicConfig() dbg = logging.getLogger('dbg') dbg.setLevel(logging.DEBUG) test

我正在玩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

是什么解释了这种行为?这是一个bug还是我遗漏了什么?

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

如果您不想将它们全部删除(谢谢):


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

[logger_stpipe]
handlers=
propagate=1
qualname=stpipe

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

而不是对未记录的
进行变异。handler

选择1 通过这种方式,您可以通过OfficeAPI完全删除先前存在的处理程序对象。或删除所有处理程序:

logger = logging.getLogger()
while logger.hasHandlers():
    logger.removeHandler(logger.handlers[0])
选择2
不仅删除,而且阻止其创建。列表根目录将为列表(testLogger.handlers)中的h提供
[]
处理程序
抱歉,我发现这不起作用。for isinstance无法用于判断处理程序的type@fat_cheng为什么iInstance不能为此目的工作?我自己使用这个答案中的建议似乎没有问题。我正在Ubuntu 16.04中使用python3。我用
if(type(h)==logging.StreamHandler)]
来代替。@fat\u cheng你永远不应该这样做,因为
type
不检查父类型(继承),
isinstance
检查:出于个人目的,我想检查一个手持设备是否在工作后没有垃圾邮件<代码>处理程序=logger.handlers;logger.error(“删除松弛处理程序”);logger.handlers=[logger.handlers if handler!=slack\u handler中的handler for handler]解决方案并不明显,因为我们需要考虑线程安全性,这一点在这里明显受到了损害(请看addHandler实现-锁用于修改处理程序列表)。一个更安全的替代方法是修改现有列表:
testLogger.handlers.clear()
@zenofpython我想
testLogger.handlers.clear()
调用
list
类型的
clear
方法?为什么它比
testLogger.handlers=[]
更安全?当您在指向原始列表的某处使用别名时,重新定义列表而不是修改原始列表是一个问题。假设:
a=b=[1,2,3]
a=[]
注意,
b
仍然指向
[1,2,3]
。公平地说,在这种情况下,您不太可能使用这样的别名,但保持一致性是一种很好的做法,这样您就不会因为走捷径而得到任何意外的惊喜。选项1不适用于非根记录器:方法
hasHandlers()
还检查祖先记录器的处理程序,因此,如果一个祖先记录器有一个处理程序,那么
logger.hashandler()
将始终计算为
True
,因此
logger.handlers[0]
将最终生成一个
索引器。
[logger_stpipe]
handlers=
propagate=1
qualname=stpipe
logging.getLogger().removeHandler(logging.getLogger().handlers[0])
logger = logging.getLogger()
while logger.hasHandlers():
    logger.removeHandler(logger.handlers[0])
logging.config.dictConfig(config={'level': logging.DEBUG, 'handlers': []}