Robert Muil
Robert Muil

Reputation: 3085

Python - showing 'once' warnings again (resetting all warning registries)

is there a way to reset the __warningregistry__ of all loaded functions at once?

I would like to force all warnings that are filtered with the 'once' filter to show again. I have found no way of doing this aside from calling <func>.__globals__['__warningregistry__'].clear() on every function that I have loaded (including those that are part of an imported module.)

So, what I want is something like a warnings.clear() function to do the following:

>>> import warnings
>>> warnings.warn('blah')
WARNING:root:blah ->UserWarning at ...
>>> warnings.warn('blah')
>>> warnings.clear()
>>> warnings.warn('blah')
WARNING:root:blah ->UserWarning at ...

And I want this warnings.clear() function to also clear all warning registries, not just the current name-space.

Is this already existent? Perhaps I'm missing something obvious, or using the module incorrectly?

Upvotes: 15

Views: 1292

Answers (3)

Catherine Devlin
Catherine Devlin

Reputation: 7743

I think that setting a filter to "always" can meet this need.

> cat warnme.py 
import warnings

for i in range(3):
    warnings.warn("oh noes!")

> python warnme.py 
warnme.py:4: UserWarning: oh noes!
warnings.warn("oh noes!")

> cat warnme2.py 
import warnings

warnings.simplefilter("always")
for i in range(3):
    warnings.warn("oh noes!")

> python warnme2.py 
warnme2.py:5: UserWarning: oh noes!
warnings.warn("oh noes!")
warnme2.py:5: UserWarning: oh noes!
warnings.warn("oh noes!")
warnme2.py:5: UserWarning: oh noes!
warnings.warn("oh noes!")

Upvotes: 0

Eli Collins
Eli Collins

Reputation: 8533

That functionality doesn't appear to exist in Python directly.

However, I needed similar functionality for my own libraries' unittests, and worked up a context manager that backs up the warning registry state for the entire process, clears it, and then restores it after the context is done.

It's a little too long to post here, but I've submitted it as a potential starting point for solving python bug 21724, so you should be able to download and use it directly from http://bugs.python.org/file40031/reset_warning_registry.py

Usage is as follows:

from reset_warning_registry import reset_warning_registry

with reset_warning_registry():
    ... do things with clear registry ...

# alternately, to just clear the warnings w/o restoring
reset_warning_registry().__enter__()

Upvotes: 6

woot
woot

Reputation: 7606

I don't believe this functionality exists, at least not in 2.7.6. I looked through the warnings.py and _warnings.c and I didn't find anything you could use to do this.

I was thinking perhaps you could wrap the module and override the warn() call to put globals()['__warningregistry__'] in a list, and add a new clear() function to loop it and reset the registry for all calls.

Upvotes: 2

Related Questions