warnings filters for varying message

Peter Otten __peter__ at web.de
Fri Jun 28 04:57:24 EDT 2013


John Reid wrote:

> Looking at the docs for warnings.simplefilter
> (http://docs.python.org/2/library/warnings.html) I think the following
> script should only produce one warning at each line as any message is
> matched by the simple filter
> 
> import warnings
> warnings.simplefilter('default')
> for i in xrange(2):
>     warnings.warn('Warning message') # This prints 1 warning
>     warnings.warn("Warning %d" % i)  # This prints 2 warnings
> 
> What do I need to do to get the warnings module just to print one
> warning for the second warnings.warn line?

$ cat warn_once_orig.py
import warnings

for i in xrange(2):
    warnings.warn('Warning message')
    warnings.warn("Warning %d" % i)
$ python -i warn_once_orig.py 
warn_once_orig.py:4: UserWarning: Warning message
  warnings.warn('Warning message')
warn_once_orig.py:5: UserWarning: Warning 0
  warnings.warn("Warning %d" % i)
warn_once_orig.py:5: UserWarning: Warning 1
  warnings.warn("Warning %d" % i)
>>> __warningregistry__
{('Warning message', <type 'exceptions.UserWarning'>, 4): True, ('Warning 
0', <type 'exceptions.UserWarning'>, 5): True, ('Warning 1', <type 
'exceptions.UserWarning'>, 5): True}

As you can see the message is part of the key that determines the identity 
of a warning. At first glance I see no official way to defeat that, so 
here's a quick hack:

$ cat warn_once.py
import warnings

class WarningMessage(str):
    def __hash__(self):
        return 0
    def __eq__(self, other):
        return isinstance(other, str)

for i in xrange(2):
    warnings.warn('Warning message')
    warnings.warn(WarningMessage("Warning %d" % i))
$ python warn_once.py 
warn_once.py:10: UserWarning: Warning message
  warnings.warn('Warning message')
warn_once.py:11: UserWarning: Warning 0
  warnings.warn(WarningMessage("Warning %d" % i))





More information about the Python-list mailing list