Why only one warning in a loop?

Question:

I want a warning raise for each problem detected in a loop, but the warning is only raised once, the first time. For example :

import warnings

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

I expect :

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

but the result is :

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

Why do I have only one warning? How can I get a warning for each iteration?

Asked By: Covich

||

Answers:

It is by design. See the docs at http://docs.python.org/2/library/warnings.html:

Repetitions of a particular warning for the same source location are typically suppressed.

You can override this behavior by adding a filter with the keyword always, as in:

import warnings

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

From the warnings module documentation:

Repetitions of a particular warning for the same source location are typically suppressed.

This is by design.

I’d not use the warnings module if you want your message to be printed always; you could reset the filters (using warnings.resetwarnings(), but that’s very much not recommended as you’d discard any user-configured filters too. You could add an explicit filter that always allows the message with the warnings.simplefilter() function:

warnings.simplefilter('always', UserWarning)

but I’d just write to sys.stderr directly instead.

Answered By: Martijn Pieters

It’d already mentioned in the other answers that, by default, each warning is printed once for each source file where it occurs. However, you could change that easily from the command line. Invoke the interpreter by saying 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
>>>
Answered By: devnull

The default filters prevents multiple occurrences of your warning – you can override the filter using simplefilter.

import warnings

warnings.simplefilter("always")
for i in range(10):
    print i
    warnings.warn('this is a warning message')
Answered By: user1152303
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.