Python 2.7.2は、ロガーのハンドラーを介して適切に反復しません

StackOverflow https://stackoverflow.com/questions/7812263

  •  26-10-2019
  •  | 
  •  

質問

次のコードは非常に単純ですが、何らかの理由で、For-Loopはロガーのすべてのハンドラーを繰り返しません。ただし、for-loopは削除するとすべてのハンドラーを繰り返します my_logger.removehandler(ハンドラー) else句で。私が何か問題を抱えているかどうかは考えていますか?

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スタイルのインデックスループと同じです。

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

したがって、ループを初めて回します i IS 0です。アイテム0が削除され、アイテムを1〜4で移動して、新しいアイテム0〜3になります。次回はループを回ります i1 したがって、現在の項目1です 2, 、削除されます。オリジナル 1 ジャンプされており、ループに残っています。

破壊的な反復を避けるための簡単な回避策は、リストのコピーを取り、オリジナルを変更しながらコピーを繰り返すことです。

for handler in list(my_logger.handlers):

使用 filter または、リストから特定のアイテムを削除しようとしている場合、通常、包括的なルートがより簡単です。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top