In Python, how does one catch warnings as if they were exceptions?

PythonExceptionException HandlingWarnings

Python Problem Overview


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?

Python Solutions


Solution 1 - Python

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 - Python

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 - Python

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 - Python

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 - Python

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

Solution 6 - Python

Expanding on niekas answer, but using the catch_warnings context manager that resets the warnings behavior to default after context exit:

import warnings

with warnings.catch_warnings():
     warnings.simplefilter("error")
     # Code in this block will raise exception for a warning
# Code in this block will have default warning behaviour

Solution 7 - Python

Just for completeness, you can also export an env variable:

PYTHONWARNINGS=error /usr/bin/run_my_python_utility

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBoris GorelikView Question on Stackoverflow
Solution 1 - PythonniekasView Answer on Stackoverflow
Solution 2 - PythonBobby PowersView Answer on Stackoverflow
Solution 3 - PythonazmeukView Answer on Stackoverflow
Solution 4 - PythonmcqwertyView Answer on Stackoverflow
Solution 5 - PythonCollin AndersonView Answer on Stackoverflow
Solution 6 - PythonCharlesBView Answer on Stackoverflow
Solution 7 - Pythonpmav99View Answer on Stackoverflow