Python's warnings module lets you issue alerts without stopping execution. Warnings are for "something might be wrong" situations—deprecations, edge cases, or recoverable issues.

Issuing Warnings

import warnings
 
def old_function():
    warnings.warn("old_function is deprecated", DeprecationWarning)
    return "still works"
 
result = old_function()
# DeprecationWarning: old_function is deprecated

Warning Categories

CategoryUse Case
UserWarningDefault, general warnings
DeprecationWarningFeature will be removed
PendingDeprecationWarningFuture deprecation
SyntaxWarningDubious syntax
RuntimeWarningRuntime issues
FutureWarningAPI changes in future versions
ImportWarningImport problems
ResourceWarningUnclosed files/connections
import warnings
 
warnings.warn("Generic warning")  # UserWarning
warnings.warn("Going away soon", DeprecationWarning)
warnings.warn("Check your math", RuntimeWarning)

Controlling Warnings

Filter by Action

import warnings
 
# Ignore all warnings
warnings.filterwarnings("ignore")
 
# Turn warnings into errors
warnings.filterwarnings("error")
 
# Show warnings once per location
warnings.filterwarnings("once")
 
# Always show
warnings.filterwarnings("always")

Filter by Category

import warnings
 
# Ignore only DeprecationWarnings
warnings.filterwarnings("ignore", category=DeprecationWarning)
 
# Error on ResourceWarnings
warnings.filterwarnings("error", category=ResourceWarning)

Filter by Message

import warnings
 
# Ignore warnings matching pattern
warnings.filterwarnings("ignore", message=".*deprecated.*")
 
# Ignore from specific module
warnings.filterwarnings("ignore", module="some_library")

Context Manager

Temporarily change warning behavior:

import warnings
 
with warnings.catch_warnings():
    warnings.simplefilter("ignore")
    # Warnings suppressed here
    risky_operation()
 
# Back to normal

Command Line Control

# Show all warnings
python -W all script.py
 
# Ignore warnings
python -W ignore script.py
 
# Warnings become errors
python -W error script.py
 
# Filter specific category
python -W ignore::DeprecationWarning script.py

In pytest

import pytest
import warnings
 
def test_warns_on_deprecated():
    with pytest.warns(DeprecationWarning):
        old_function()
 
def test_no_warnings():
    with warnings.catch_warnings():
        warnings.simplefilter("error")
        # Any warning = test failure
        clean_function()

Custom Warning Format

import warnings
 
def custom_format(msg, category, filename, lineno, line=None):
    return f"⚠️ {category.__name__}: {msg}\n"
 
warnings.formatwarning = custom_format
 
warnings.warn("Something's off")
# ⚠️ UserWarning: Something's off

Practical Patterns

Deprecation Helper

import warnings
import functools
 
def deprecated(message):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            warnings.warn(
                f"{func.__name__} is deprecated: {message}",
                DeprecationWarning,
                stacklevel=2
            )
            return func(*args, **kwargs)
        return wrapper
    return decorator
 
@deprecated("Use new_function instead")
def old_function():
    pass

Warn Once Pattern

import warnings
 
_warned = set()
 
def warn_once(key, message, category=UserWarning):
    if key not in _warned:
        warnings.warn(message, category, stacklevel=2)
        _warned.add(key)
 
# Only warns on first call
warn_once("slow_path", "Using slow fallback")
warn_once("slow_path", "Using slow fallback")  # Silent

Resource Warning

import warnings
 
class ManagedResource:
    def __init__(self):
        self.closed = False
    
    def close(self):
        self.closed = True
    
    def __del__(self):
        if not self.closed:
            warnings.warn(
                "Resource not properly closed",
                ResourceWarning,
                stacklevel=2
            )

stacklevel Parameter

Control where the warning appears to come from:

import warnings
 
def helper():
    warnings.warn("issue", stacklevel=1)  # Points to this line
 
def helper2():
    warnings.warn("issue", stacklevel=2)  # Points to caller
 
helper()   # Warning shows helper() as source
helper2()  # Warning shows your code as source

Use stacklevel=2 when the warning should point at the caller, not your internal function.

Logging Integration

Send warnings to logging:

import logging
import warnings
 
logging.captureWarnings(True)
logger = logging.getLogger("py.warnings")
logger.addHandler(logging.StreamHandler())
 
warnings.warn("This goes to logging")

Summary

The warnings module is for non-fatal alerts:

  • warn() to issue warnings
  • filterwarnings() to control visibility
  • catch_warnings() for temporary changes
  • Use appropriate categories (DeprecationWarning, RuntimeWarning, etc.)
  • Set stacklevel=2 in helper functions

Warnings are gentler than exceptions—they inform without stopping execution.

React to this post: