Python 2.7.2 неправильно перебирает обработчики логгера - PullRequest
1 голос
/ 18 октября 2011

следующий код очень прост, но по какой-то причине цикл for не выполняет итерацию по всем обработчикам регистратора.однако цикл for выполняет итерацию всех обработчиков, если мы удалим my_logger.removeHandler (handler) в предложении 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

1 Ответ

2 голосов
/ 18 октября 2011

Это классическая разрушительная итерация. Что вы делаете это:

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

В этом примере удаляется только каждый второй элемент. Зачем? Хорошо, синтаксис for ... in скрывает то, что происходит на самом деле, что аналогично традиционному циклу for-index в стиле C:

>>> 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. В следующий раз цикл i равен 1, поэтому текущий элемент 1, который равен 2, удаляется. Оригинал 1 был перепрыгнут и остается в цикле.

Простой обходной путь, позволяющий избежать разрушительной итерации, - это взять копию списка и выполнить итерацию копии при изменении оригинала:

for handler in list(my_logger.handlers):

Использование filter или списочных представлений обычно является более простым способом, когда вы пытаетесь удалить определенные элементы из списка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...