In Google Colab, when I run the following:
def f():
import warnings
warnings.warn("deprecated", DeprecationWarning, stacklevel=2)
def g():
return f()
def h():
return g()
h() # or f() or g()
I get 1 warning in the output:
<ipython-input-9-e09ca081f372>:6: DeprecationWarning: deprecated
return f()
And when I run:
f()
g()
h()
I get only 2 warnings(I expected 3 warnings because all 3 functions were called):
<ipython-input-10-0d5243608655>:1: DeprecationWarning: deprecated
f()
<ipython-input-9-e09ca081f372>:6: DeprecationWarning: deprecated
return f()
Now, I tried the same in Terminal Python and I only got warnings for f()
and g()
and not for h()
Python 3.11.1 (main, Feb 5 2023, 16:11:00) [Clang 13.1.6 (clang-1316.0.21.2.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> def f():
... import warnings
... warnings.warn("deprecated", DeprecationWarning, stacklevel=2)
...
>>> def g():
... return f()
...
>>> def h():
... return g()
...
>>> f()
<stdin>:1: DeprecationWarning: deprecated
>>> g()
<stdin>:2: DeprecationWarning: deprecated
>>> h()
>>>
I wanted to understand:
h()
individually but not when I run it with f()
and g()
in the same cell? and why does h()
never shows a warning in Terminal Python(I think it is because stacklevel=2
)? And how exactly running a warning code in colab different from running a warning code in Terminal Python?f()
is called, by me or by some wrapper function?stacklevel
and skip_file_prefixes
fit in all this?Thank you :)
This is due to the default warning filter, which will only print the first occurrence of a warning for each location. With stacklevel=2
, the warning location is where f()
was called, which is <ipython-input-10-0d5243608655>:1
when you call f()
directly in the notebook, and <ipython-input-9-e09ca081f372>:6
inside of g()
when you call g()
directly or indirectly via h()
. The same logic applies to the terminal session. Note that if you call h()
before g()
, the warning will be printed after h()
instead:
Python 3.12.3 (main, Apr 17 2024, 00:00:00) [GCC 13.2.1 20240316 (Red Hat 13.2.1-7)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> def f():
... import warnings
... warnings.warn("deprecated", DeprecationWarning, stacklevel=2)
...
>>> def g():
... return f()
...
>>> def h():
... return g()
...
>>> f()
<stdin>:1: DeprecationWarning: deprecated
>>> h()
<stdin>:2: DeprecationWarning: deprecated
>>> g()
>>> g()
>>> h()
>>>
The inconsistency between the notebook and the terminal is probably this issue: https://github.com/ipython/ipython/issues/11207
If you want the warning to be printed on every call, you can change the warning filter programmatically by running warnings.simplefilter("always")
.