Warning

A warning is an exception class that is normally not raised: warnings.warn() hands it to the filters, which print it once, ignore it, or — with "error" — raise it like any other exception.

InheritsBaseException›Exception›Warning
Warning categoryPython 3 (all)Live demo
Warning(*args)
Raised by
warnings.warn(msg, Category), the compiler (SyntaxWarning), the runtime (RuntimeWarning, ResourceWarning)
Message
file.py:12: UserWarning: text (printed to stderr)
Quick fix
silence one: filterwarnings('ignore', message=…, category=…)
Watch out
shown once per location by default — a loop does not repeat it

Demo

Live evaluation
The same warnings.warn() call runs 3 times under a filter action of your choice. catch_warnings(record=True) collects what would have been printed.
Try:
Inputs
actionstrerror ignore always default module once
Code
import warnings
with warnings.catch_warnings(record=True) as caught:
    warnings.simplefilter('default')
    for i in range(3):
        warnings.warn('old API', UserWarning)
[str(w.message) for w in caught]
Result
['old API']

Compare default and always: the default action records the warning once for that line, so a warning inside a loop appears a single time; always records all three. error stops at the first call with an uncaught UserWarning — that is what python -W error does to your whole program. The action must be spelled exactly: 'Error' is a ValueError, not a filter.

Constructor

NameTypeRequiredDescription
*argsobjectnoThe message. warnings.warn(text, Category) builds Category(text) for you.

Attributes

AttributeTypeMeaning
argstupleThe constructor arguments; args[0] is the message text.
w.message / w.category / w.filename / w.linenorecord fieldsWith catch_warnings(record=True) each recorded item carries the Warning instance, its class, and the location it is attributed to (see stacklevel).

Common patterns

Warn from your own code
Pick a category, and stacklevel=2 so the report points at the caller that needs changing.
import warnings

def connect(host, timeout=None):
    if timeout is None:
        warnings.warn('no timeout set; connections may hang', RuntimeWarning, stacklevel=2)
Silence one specific warning
Match by message (a regex matched at the start) and category instead of switching everything off.
import warnings
warnings.filterwarnings('ignore', message='.*unclosed.*', category=ResourceWarning)
Make warnings fail in tests
Same as running python -W error: any warning becomes an exception. In pytest: -W error or the filterwarnings ini option.
import warnings

def test_no_warnings():
    with warnings.catch_warnings():
        warnings.simplefilter('error')
        run_the_code()

Examples

1. Default category is UserWarning
import warnings with warnings.catch_warnings(record=True) as caught: warnings.simplefilter('always') warnings.warn('careful') (caught[0].category.__name__, str(caught[0].message))
Returns
('UserWarning', 'careful')
2. 'error' raises it
import warnings with warnings.catch_warnings(): warnings.simplefilter('error') warnings.warn('careful')
Returns
UserWarning: careful
3. All built-in categories
sorted(c.__name__ for c in Warning.__subclasses__() if c.__module__ == 'builtins')
Returns
['BytesWarning', 'DeprecationWarning', 'EncodingWarning', 'FutureWarning', 'ImportWarning', 'PendingDeprecationWarning', 'ResourceWarning', 'RuntimeWarning', 'SyntaxWarning', 'UnicodeWarning', 'UserWarning']
4. SyntaxWarning from the compiler
import warnings with warnings.catch_warnings(record=True) as caught: warnings.simplefilter('always') compile(r"'\d'", '<demo>', 'eval') [(w.category.__name__, str(w.message)) for w in caught]
Returns
[('SyntaxWarning', "invalid escape sequence '\\d'")]
5. SyntaxWarning as error becomes SyntaxError
import warnings with warnings.catch_warnings(): warnings.simplefilter('error') compile(r"'\d'", '<demo>', 'eval')
Returns
SyntaxError: invalid escape sequence '\d'
6. RuntimeWarning: coroutine never awaited
import warnings async def fetch(): return 1 with warnings.catch_warnings(record=True) as caught: warnings.simplefilter('always') fetch() [(w.category.__name__, str(w.message)) for w in caught]
Returns
[('RuntimeWarning', "coroutine 'fetch' was never awaited")]
7. ResourceWarning: file never closed
import warnings with warnings.catch_warnings(record=True) as caught: warnings.simplefilter('always') f = open('data.txt', 'w') del f [w.category.__name__ for w in caught]
Returns
['ResourceWarning']
8. stacklevel=2 blames the caller
import warnings def old(x): warnings.warn('old() is deprecated', DeprecationWarning, stacklevel=2) return x with warnings.catch_warnings(record=True) as caught: warnings.simplefilter('always') old(1) [w.lineno for w in caught]
Returns
[7]

Pitfalls

1. Blanket ignore hides warnings you need
simplefilter('ignore') also swallows deprecations and resource leaks from your own code. Filter by message and category.
Ignore everything
import warnings
with warnings.catch_warnings(record=True) as caught:
    warnings.simplefilter('ignore')
    warnings.warn('noisy library message')
    warnings.warn('important')
[str(w.message) for w in caught]
[]
Ignore one message
import warnings
with warnings.catch_warnings(record=True) as caught:
    warnings.simplefilter('always')
    warnings.filterwarnings('ignore', message='noisy')
    warnings.warn('noisy library message')
    warnings.warn('important')
[str(w.message) for w in caught]
['important']
2. Passing the category as a string
The second argument is a class, not its name.
'UserWarning'
import warnings
warnings.warn('x', 'UserWarning')
TypeError: category must be a Warning subclass, not 'str'
UserWarning
import warnings
with warnings.catch_warnings(record=True) as caught:
    warnings.simplefilter('always')
    warnings.warn('x', UserWarning)
len(caught)
1
3. Filters are ordered: the newest wins
simplefilter and filterwarnings insert at the front of the list, so a later, more general call overrides an earlier specific one.
Specific first
import warnings
with warnings.catch_warnings(record=True) as caught:
    warnings.simplefilter('always', UserWarning)
    warnings.simplefilter('error')
    warnings.warn('shown, not raised')
len(caught)
UserWarning: shown, not raised
General first
import warnings
with warnings.catch_warnings(record=True) as caught:
    warnings.simplefilter('error')
    warnings.simplefilter('always', UserWarning)
    warnings.warn('shown, not raised')
len(caught)
1

When to use

Use it
  • Something works but is probably a mistake or will change — the caller should hear about it without crashing
  • Library code: deprecations, odd-but-legal arguments, fallbacks that lose performance
  • Subclass a category (class ConfigWarning(UserWarning)) so users can filter yours precisely
Reach for something else
  • The operation cannot continue → raise a real exception
  • Diagnostics for operators of a service → logging (logging.captureWarnings(True) routes warnings there)

Notes

CPython impl
Python/_warnings.c — the C implementation behind warnings.warn(); Lib/warnings.py holds filters, catch_warnings and formatting
Default filters
Release builds ignore DeprecationWarning (except in __main__), PendingDeprecationWarning, ImportWarning and ResourceWarning; -X dev shows them all
Command line
python -W error, -W ignore::DeprecationWarning, or PYTHONWARNINGS=… set filters before your code runs
Categories
UserWarning (default), DeprecationWarning, PendingDeprecationWarning, FutureWarning, SyntaxWarning, RuntimeWarning, ImportWarning, UnicodeWarning, BytesWarning, ResourceWarning, EncodingWarning

FAQ

Run python -W error script.py (or set PYTHONWARNINGS=error), or call warnings.simplefilter('error') — inside warnings.catch_warnings() to limit it to a block. The warning is then raised as an exception of its category and can be caught with except UserWarning, except DeprecationWarning, or except Warning.