🎓 A1Learner
🔍

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?