Почему только одно предупреждение в цикле?

Мне нужно повышение предупреждения для каждой проблемы, обнаруженной в цикле, но предупреждение возникает только один раз, в первый раз. Например:

import warnings

for i in range(10):
   print i
   warnings.warn('this is a warning message')

Я ожидаю:

0
UserWarning: this is a warning message
1
UserWarning: this is a warning message
2
UserWarning: this is a warning message
3
UserWarning: this is a warning message
4

но результат:

0
__main__:4: UserWarning: this is a warning message
1
2
3
4

Почему у меня есть только одно предупреждение? Как я могу получить предупреждение для каждой итерации?

Ответы

Ответ 1

Это по дизайну. См. Документы в http://docs.python.org/2/library/warnings.html:

Повторения определенного предупреждения для одного и того же исходного местоположения обычно подавляются.

Вы можете переопределить это поведение, добавив фильтр с ключевым словом always, как в:

import warnings

warnings.simplefilter('always', UserWarning)
for i in range(10):
   print i
   warnings.warn('this is a warning message')

Ответ 2

Из документации warnings:

Повторения определенного предупреждения для одного и того же исходного местоположения обычно подавляются.

Это по дизайну.

Я бы не использовал модуль warnings, если вы хотите, чтобы ваше сообщение всегда печаталось; вы могли бы reset фильтровать (используя warnings.resetwarnings(), но это очень не, рекомендованное по мере того, как вы отбрасываете любые настраиваемые пользователем фильтры. Вы можете добавить явный фильтр, который всегда позволяет сообщению с функцией warnings.simplefilter():

warnings.simplefilter('always', UserWarning)

но я просто напишу только sys.stderr.

Ответ 3

В других ответах уже упоминалось, что по умолчанию каждое предупреждение печатается один раз для каждого исходного файла, где он встречается. Однако вы можете легко это изменить из командной строки. Вызовите интерпретатора, сказав python -W all:

$ python -W all
Python 2.7.6 (default, Mar 16 2014, 23:42:21)
[GCC 4.5.3] on netbsd6
Type "help", "copyright", "credits" or "license" for more information.
>>> import warnings
>>> for i in range(10):
   print i
   warnings.warn('this is a warning message')... ...
...
0
__main__:3: UserWarning: this is a warning message
1
__main__:3: UserWarning: this is a warning message
2
__main__:3: UserWarning: this is a warning message
3
__main__:3: UserWarning: this is a warning message
4
__main__:3: UserWarning: this is a warning message
5
__main__:3: UserWarning: this is a warning message
6
__main__:3: UserWarning: this is a warning message
7
__main__:3: UserWarning: this is a warning message
8
__main__:3: UserWarning: this is a warning message
9
__main__:3: UserWarning: this is a warning message
>>>

Ответ 4

Фильтры по умолчанию предотвращают множественные появления вашего предупреждения - вы можете переопределить фильтр с помощью simplefilter.

import warnings

warnings.simplefilter("always")
for i in range(10):
    print i
    warnings.warn('this is a warning message')