You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
(I suspect this has come up before but I couldn't find an existing issue for it.)
The expected default behavior in Python for handling warnings is such that once a specific warning has been displayed once, it should not be displayed again (unless the warning filters are updated). E.g.:
Python 3.6.1 (default, Feb 21 2018, 12:59:49)
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import warnings
>>> def foo():
... warnings.warn('foo')
...
>>> foo()
__main__:2: UserWarning: foo
>>> foo()
>>>
However, in IPython CLI this behavior is not observed (probably same for the notebook but I haven't tested):
Python 3.6.1 (default, Feb 21 2018, 12:59:49)
Type "copyright", "credits" or "license" for more information.
IPython 5.5.0 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.
In [1]: import warnings
In [2]: def foo():
...: warnings.warn('foo')
...:
In [3]: foo()
.../local/bin/ipython3:2: UserWarning: foo
# EASY-INSTALL-ENTRY-SCRIPT: 'ipython==5.5.0','console_scripts','ipython3'
In [4]: foo()
.../local/bin/ipython3:2: UserWarning: foo
# EASY-INSTALL-ENTRY-SCRIPT: 'ipython==5.5.0','console_scripts','ipython3'
I have documented the cause of this behavior here, and I believe it is more of a CPython bug than an IPython bug. But it's possible there's a workaround that could be applied, or at the very least I thought the issue should be noted.
Incidentally it seems this behavior is broken on Python 2 as well, but in that case I'm not sure what the reason is...
I see, this is #6611. So that's intentional. I don't agree with the solution though--it's even more brute-force than the Python 3 bug since it basically breaks the intended behavior (although I understand why a workaround was needed...)
On second thought, that only impacts code that was entered interactively. It won't affect code from modules so I'm okay with that. Then we're just left with the Python 3 issue which, unfortunately, impacts warnings regardless where they come from....
I believe a configuration option would be useful here. While I understand the rationale behind #6680 it would also be nice to be able to get back more "standard" behavior w.r.t. warnings, even if it's not the default.
That would do nothing to help with the upstream issue, but it would be good to have either way.
I spend some hours trying to get "once" warning only display once in IPython 9.12.0 with python 3.14.3 and now I am giving up due to a lack of time. Here are my findings in case anybody else wants to try. I was using this little helper
defpersistent_ipython_warning_registry():
importIPythonip=IPython.get_ipython()
ifipisNone:
returnclear_warning_registry_callbacks= [
cbforcbinip.events.callbacks["pre_execute"]
if"clear_warning_registry"incb.__name__
]
ifnotclear_warning_registry_callbacks:
logging.getLogger(__name__).info("No warning registry clearing callback found")
eliflen(clear_warning_registry_callbacks) ==1:
ip.events.callbacks["pre_execute"].remove(clear_warning_registry_callbacks[0])
logging.getLogger(__name__).info("Cleared warning registry callback")
else:
warnings.warn("Multiple candidates found in the IPython EventManager")
to make globals()["__warningregistry__"] persistent but sadly this did not fix the problem.
Apparently something touches the warnings filter list in every cell execution. This modifies CPython's internal st->filters_version counter. If filters_version does not match the version key in the warnings registry the registry gets cleared in warnings.warn_explicit.
Another thing which makes this more complicated is that the CPython implementation from _warnings and the pure python implementation in _py_warnings differ in behavior.
CPython uses onceregistry only if the registry argument is None(source) while the pure python implementation (source) always uses onceregistry for "once" actions.
The filters_version of CPython is not accessible from the interpreter. It is increased every time the lock for mutating the filter list is acquired with warnings._filters_mutated_lock_held.
This is done every time warnings.catch_warnings or warnings.simplefilter are called which happens 6 times for each cell execution in my setup.
Activity
embray commentedon Jun 28, 2018
Incidentally it seems this behavior is broken on Python 2 as well, but in that case I'm not sure what the reason is...
embray commentedon Jun 28, 2018
I see, this is #6611. So that's intentional. I don't agree with the solution though--it's even more brute-force than the Python 3 bug since it basically breaks the intended behavior (although I understand why a workaround was needed...)
On second thought, that only impacts code that was entered interactively. It won't affect code from modules so I'm okay with that. Then we're just left with the Python 3 issue which, unfortunately, impacts warnings regardless where they come from....
Carreau commentedon Jun 28, 2018
Hum, I can see how this can be annoying in the REPL.
We switched the default on purpose, as you noted in #6611, and #6680. Would a configuration option to disable this behavior suits you ?
If there is an upstream issue with Python, the fix will depends on the cost/benefits ratio.
embray commentedon Jun 28, 2018
I believe a configuration option would be useful here. While I understand the rationale behind #6680 it would also be nice to be able to get back more "standard" behavior w.r.t. warnings, even if it's not the default.
That would do nothing to help with the upstream issue, but it would be good to have either way.
Workaround for a duplicate warnings bug triggered by pandas DataFrame
Make sure we don't crash on unknown types returned by the backend. (#155
shumpohl commentedon Apr 16, 2026
I spend some hours trying to get "once" warning only display once in IPython 9.12.0 with python 3.14.3 and now I am giving up due to a lack of time. Here are my findings in case anybody else wants to try. I was using this little helper
to make
globals()["__warningregistry__"]persistent but sadly this did not fix the problem.Apparently something touches the warnings filter list in every cell execution. This modifies CPython's internal
st->filters_versioncounter. Iffilters_versiondoes not match theversionkey in the warnings registry the registry gets cleared inwarnings.warn_explicit.Another thing which makes this more complicated is that the CPython implementation from
_warningsand the pure python implementation in_py_warningsdiffer in behavior.CPython uses
onceregistryonly if theregistryargument isNone(source) while the pure python implementation (source) always usesonceregistryfor "once" actions.The
filters_versionof CPython is not accessible from the interpreter. It is increased every time the lock for mutating the filter list is acquired withwarnings._filters_mutated_lock_held.This is done every time
warnings.catch_warningsorwarnings.simplefilterare called which happens 6 times for each cell execution in my setup.Carreau commentedon Apr 19, 2026
probably #6611 ? So on purpose?