Issue and Control Warnings with Python's warnings Module
Warn callers about deprecated or questionable API use, choose warning categories, control filters, and test warning behavior.
Intermediate
Use a warning when code should alert a caller about a questionable or changing API use but can still continue. Raise an exception when the operation cannot proceed normally; use logging to record runtime events for diagnosis. A warning does not stop a program unless its filter turns that warning into an exception.
Warn without automatically stopping the program
Call warnings.warn() to report an advisory condition. The default category is UserWarning. Warnings normally go to standard error, and Python filters decide whether to show, ignore, or escalate them. The next example captures a warning so its behavior can be examined without noisy terminal output.
Output
Ready to run.
Quick check
What normally happens after warnings.warn() emits a warning that is not filtered into an error?
answer = "operation continues"
print(answer)
Choose a category for the intended audience
Use UserWarning for application-level warnings by default. DeprecationWarning is intended mainly for Python developers who need to update their code; it is usually ignored outside __main__. FutureWarning is intended for end users of applications when a behavior is changing. Pick the category based on who needs to act, not merely on how serious the message sounds.
Output
Ready to run.
Quick check
Which category is intended for a deprecation warning aimed primarily at developers using an API?
import warnings
print(issubclass(DeprecationWarning, Warning))
Point warnings to the caller
When a helper function emits a warning on behalf of its caller, pass stacklevel=2 so the warning points to the call site instead of the line inside the helper. This helps users find the line they need to change. Use a larger stacklevel only when the wrapper depth requires it; a wrong level can point to an unrelated line.
Output
Ready to run.
Quick check
In a warning helper, what does stacklevel=2 normally do?
import warnings
warnings.warn("Use new_api()", DeprecationWarning, stacklevel=2)
Control warnings with filters
Warning filters control disposition. Common actions are default (show the first matching occurrence at a location), always, ignore, once, and error. The error action raises the warning category as an exception, so code can deliberately make selected warnings fail a test or check. Prefer a scoped catch_warnings() block when experimenting in a small piece of code, so the prior filter list is restored afterward.
Output
Ready to run.
Quick check
Which filter action makes a matching warning raise its warning category as an exception?
import warnings
warnings.simplefilter("error", UserWarning)
Test warnings deliberately
Use catch_warnings(record=True) with simplefilter("always") to test that code emits the expected category and message. The always action avoids suppression when a test intentionally emits the same warning more than once. Check both that a warning occurred and that its category/message is appropriate; do not globally silence warnings just to make a test suite quiet.
Output
Ready to run.
Quick check
When a test needs to inspect every emitted warning, which setup is the most reliable?
import warnings
with warnings.catch_warnings(record=True) as seen:
warnings.simplefilter("always")
Key takeaways
- A warning communicates an advisory condition; it does not normally stop execution unless a filter escalates it.
- Choose the category for its intended audience: UserWarning by default, DeprecationWarning for developers, and FutureWarning for application users.
- Use stacklevel to point to the caller when a helper emits a warning on its behalf.
- Filters can display, suppress, repeat, or turn matching warnings into exceptions.
- Use catch_warnings(record=True) and a temporary always filter to test warning categories and messages.
Quick check recap
Thanks for your feedback.
Mark this learning resource complete to track your learning progress.