以下代码非常简单,但是由于某些原因,循环并不能通过记录器的所有处理程序迭代。但是,如果我们删除 my_logger.removehandler(处理程序) 在其他条款中。知道我做错了什么吗?

import logging
import sys

stdf = logging.Formatter( "%(message)s" )
filef = logging.Formatter( "%(message)s" )
my_logger = logging.getLogger( "file std logger" )
stdh = logging.StreamHandler( sys.stdout )
stdh.setFormatter( stdf )
my_logger.addHandler( stdh )
fileh = logging.FileHandler( "run.log", mode = 'w', encoding = "utf-16-le", delay = True )
fileh.setLevel( logging.DEBUG )
fileh.setFormatter( filef )
my_logger.addHandler( fileh )

my_logger.info("wow1")
my_logger.info("test string1")
my_logger.info("wow2")
my_logger.info("test string2")
my_logger.info("wow3")
my_logger.info("test string3")

for handler in my_logger.handlers:
    print(handler)
    if handler.__class__.__name__ == "FileHandler":
        handler.flush()
        handler.close()
        my_logger.removeHandler( handler )
    else:
        handler.flush()
        my_logger.removeHandler( handler )

my_logger.handlers
有帮助吗?

解决方案

这是经典的破坏性迭代。您正在做的是:

>>> l= [0, 1, 2, 3, 4]
>>> for n in l:
...     l.remove(n)
... 
>>> l
[1, 3]

在此示例中,仅删除每个第二个元素。为什么?好吧 for...in 语法掩盖了实际发生的事情,这与传统的C风格的For-Index循环相同:

>>> l= [0, 1, 2, 3, 4]
>>> i= 0
>>> while i<len(l):
...     del l[i]
...     i+= 1
...
>>> l
[1, 3]

所以第一次四处循环 i 是0。项目0被删除,将项目1–4向下移动,将其作为新项目0-3。下次循环 i1 因此,当前项目1是 2, , 已移除。原本的 1 已经跳了起来并留在循环中。

避免破坏性迭代的一个简单的解决方法是获取列表的副本,并在更改原件的同时迭代副本:

for handler in list(my_logger.handlers):

使用 filter 当您尝试从列表中删除某些项目时,通常是更简单的途径。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top