Python The contextlib Module
contextlib is a standard library module full of context manager helpers.
A manager as a generator
The decorator does the class work for you. The yield line marks where the block runs.
from contextlib import contextmanager
@contextmanager
def shout():
print("BEFORE")
yield
print("AFTER")
with shout():
print("middle")try and finally guard the yield
Wrap yield in try and finally for safe cleanup. The finally part runs even on an error.
from contextlib import contextmanager
@contextmanager
def careful():
print("Start")
try:
yield
finally:
print("Always runs")
try:
with careful():
raise ValueError("demo error")
except ValueError:
print("Caught outside")suppress() ignores a known error
To suppress an error means to let it happen quietly. Use it only for errors you expect.
from contextlib import suppress
with suppress(ValueError):
number = int("not a number")
print("Carried on")closing() wraps a close() method
Some objects have close() but no __enter__ or __exit__. The closing helper bridges that gap.
from contextlib import closing
class Jar:
def close(self):
print("Jar closed")
with closing(Jar()) as jar:
print("Using the jar")Example
from contextlib import contextmanager, suppress
@contextmanager
def tag(name):
print(f"<{name}>")
try:
yield
finally: print(f"</{name}>")
with tag("section"):
print("Hello inside")
with suppress(FileNotFoundError):
open("no_such_file.txt").read()
print("No crash")Key points
- contextlib: a standard library module full of context manager helpers
- Use @contextlib.contextmanager to turn a generator function into a context manager
- The code before yield runs when the block starts
- The code after yield runs when the block ends
- Use suppress(...) to ignore listed errors that you know are harmless
- Use closing(x) to wrap an object that has close() but no manager methods
In this example, tag is the Tag manager from the last lesson. It now takes six lines, counting the decorator line. The print before the try runs on entry. The yield is where the block runs. The finally line prints the closing label on exit. The second with block uses suppress with FileNotFoundError. The named file does not exist, so open raises that error. The suppress helper swallows it quietly. The last line prints to prove the program carried on.
Note
suppress() hides only the error types you list.
Any other error still spreads as usual.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Python Playground
Exercise
In a function decorated with @contextmanager, where does cleanup code belong?