Python The warnings Module
A warning is a message about code that still works.
Send and capture a warning
Warnings normally go to the error stream. catch_warnings with record=True saves them in a list instead.
import warnings
with warnings.catch_warnings(record=True) as caught:
warnings.simplefilter("always")
warnings.warn("Disk is almost full", UserWarning)
print(len(caught))
print(caught[0].category.__name__)
print(str(caught[0].message))Categories name the kind
Each warning carries a category. Code can later filter or test by that category.
import warnings
with warnings.catch_warnings(record=True) as caught:
warnings.simplefilter("always")
warnings.warn("Plain caution", UserWarning)
warnings.warn("Old name", DeprecationWarning)
print(caught[0].category.__name__)
print(caught[1].category.__name__)A filter can ignore warnings
The ignore filter drops matching warnings. Nothing reaches the captured list here.
import warnings
with warnings.catch_warnings(record=True) as caught:
warnings.simplefilter("ignore")
warnings.warn("Old path", DeprecationWarning)
print(len(caught))A filter can raise warnings
The error filter turns a warning into an exception. Tests use this to fail on new warnings.
import warnings
with warnings.catch_warnings():
warnings.simplefilter("error")
try:
warnings.warn("Careful", UserWarning)
except UserWarning:
print("Warning became an error")Example
import warnings
def fetch_user(name):
return f"User: {name}"
def fetch_user_old(name):
warnings.warn("fetch_user_old is old. Use fetch_user.", DeprecationWarning)
return fetch_user(name)
with warnings.catch_warnings(record=True) as caught:
warnings.simplefilter("always")
print(fetch_user_old("Ada"))
print(fetch_user("Cy"))
print(len(caught))
print(caught[0].category.__name__)
print(str(caught[0].message))Key points
- Warning: a message that says code works, but something deserves attention
- Use warnings.warn(message, Category) to send a warning
- Category: the kind of a warning, such as UserWarning or DeprecationWarning
- DeprecationWarning: a warning that a feature is on its way out
- Use warnings.catch_warnings(record=True) to capture warnings in a test
- Use warnings.simplefilter("always") inside a capture, so nothing is filtered away
In this example, fetch_user is the new function and it stays silent. The old name, fetch_user_old, still works for old callers. It warns with DeprecationWarning before doing its work. The with block captures warnings instead of printing them to the error stream. The simplefilter line set to always keeps every warning. Both calls print their user lines as normal. The capture list then holds exactly one warning. Its category is DeprecationWarning, and its message names the new function.
Note
Python hides DeprecationWarning in many places by default, so tests capture warnings instead of trusting the screen.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Python Playground
Exercise
A function still works, but its name will change in the next version. What should it do?