In Python, how does one catch warnings as if they were exceptions?
Solution 1
To handle warnings as errors simply use this:
import warnings
warnings.filterwarnings("error")
After this you will be able to catch warnings same as errors, e.g. this will work:
try:
some_heavy_calculations()
except RuntimeWarning:
import ipdb; ipdb.set_trace()
P.S. Added this answer because the best answer in comments contains misspelling: filterwarnigns
instead of filterwarnings
.
Solution 2
To quote from the python handbook (27.6.4. Testing Warnings):
import warnings
def fxn():
warnings.warn("deprecated", DeprecationWarning)
with warnings.catch_warnings(record=True) as w:
# Cause all warnings to always be triggered.
warnings.simplefilter("always")
# Trigger a warning.
fxn()
# Verify some things
assert len(w) == 1
assert issubclass(w[-1].category, DeprecationWarning)
assert "deprecated" in str(w[-1].message)
Solution 3
If you just want your script to fail on warnings you can invoke python
with the -W
argument:
python -W error foobar.py
Solution 4
Here's a variation that makes it clearer how to work with only your custom warnings.
import warnings
with warnings.catch_warnings(record=True) as w:
# Cause all warnings to always be triggered.
warnings.simplefilter("always")
# Call some code that triggers a custom warning.
functionThatRaisesWarning()
# ignore any non-custom warnings that may be in the list
w = filter(lambda i: issubclass(i.category, UserWarning), w)
if len(w):
# do something with the first warning
email_admins(w[0].message)
Solution 5
In some cases, you need use ctypes to turn warnings into errors. For example:
str(b'test') # no error
import warnings
warnings.simplefilter('error', BytesWarning)
str(b'test') # still no error
import ctypes
ctypes.c_int.in_dll(ctypes.pythonapi, 'Py_BytesWarningFlag').value = 2
str(b'test') # this raises an error
Related videos on Youtube
Boris Gorelik
Updated on August 07, 2021Comments
-
Boris Gorelik over 2 years
A third-party library (written in C) that I use in my python code is issuing warnings. I want to be able to use the
try
except
syntax to properly handle these warnings. Is there a way to do this?-
Fenikso about 13 yearsAre those warning just text messages written do stderr?
-
Boris Gorelik about 13 yearsFenikso: I don't know for sure, seems like real warnings
-
Fenikso about 13 yearsHow do you recognize "real warning"? I thought that in C you get real warning during compile.
-
Rosh Oxymoron about 13 years
warnings.filterwarnings
does exactly what you want, I don't understand what your issue with it is? -
Boris Gorelik about 13 years@Fenikso, @Rosh Oxymoron you were right. My mistake.
warnings.filterwarnigns('error')
does the job. I can't find the original answer that proposed this solution
-
-
Unapiedra over 9 years
-
z0r about 7 yearsAnd if you just want to see a stack trace, the first two lines are all you need.
-
Praveen almost 7 yearsThis is perfect. I just wanted my script to stop execution as soon as the warning was issued, so that I could print relevant debug information and fix the issue.
-
Pietro Battiston about 5 yearsThis has the advantage, over niekas's answer, that if
fnx
returns something, you keep that result (and still can manage the warning). -
naught101 about 5 yearsYou don't need the
filterwarnings
call in order to catchWarnings
, at least in python 3. it just works. -
AlanSE about 5 yearsThis answer is constructive simply for showing how to error only in certain warning types. For almost any large software project, if you do
warnings.simplefilter('error')
you won't get the traceback for the warning you saw in the logs, but instead get tracebacks from previously-filtered warnings. Usingsimplefilter
is also the quickest way to arrive at your answer if you have some CLI invocation. -
Biggsy about 4 yearsThe accepted answer does not answer the OP's question. This answer does. This is the answer I was looking for when my search found this question.
-
Biggsy about 4 yearsThis does not answer the OP's question, which was about handling wanrings, not testing them. However, the answer by niekas below does show how to handle warnings.
-
Steven M. Mortimer almost 4 yearsJust a note that the above function will not work if your function only intermittently returns a warning because in the event that
fxn()
does not return a warning, thenw
will be an empty list. Ifw
is an empty list (i.e.[]
), then running the code will give you the following error:IndexError: list index out of range
. If you're just looking to format or check properties of the captured warnings, then it's better to use a for-loop:for x in w: print(f'{x.category.__name__}: {str(x.message)}')
-
Ben Jeffrey over 3 yearsConverting all warnings to errors can easily become problematic if you're using this within a larger script or software package. Can make things very hard to debug as well
-
normanius about 3 yearsThis approach is useful if one wants to handle warnings without interrupting program execution.
-
Paul Price over 2 yearsTo catch a specific warning type, e.g.:
python -W error::RuntimeWarning foobar.py