contextlib
The contextlib module gives you tools for working with the with-statement — most notably @contextmanager, which turns a simple generator into a reusable setup-and-cleanup context manager.
Learn contextlib in our free Python course — an interactive lesson with runnable examples, a practice exercise and a quick reference.
Part of the free Python course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
You'll also meet suppress for ignoring specific errors, redirect_stdout for capturing output, and ExitStack for managing a dynamic number of resources at once.
The @contextmanager decorator turns a generator into a context manager. Code before yield is the setup (runs on entering the with ); code after yield is the cleanup (runs on exit, even if an error occurs):
suppress(SomeError) swallows a specific exception so the program keeps going — a clean replacement for try/except: pass . redirect_stdout(buffer) captures everything print() writes into a string buffer instead of the screen:
ExitStack manages a dynamic number of context managers. You call stack.enter_context(cm) for each one, and when the with block ends, all of them are exited in reverse order. Below, three resources are opened from a list and closed automatically:
And closing() adapts any object with a close() method into a context manager:
Replace each ___ to finish a context manager that prints a banner before and after the block.
If cleanup must always run, it belongs after the yield (ideally guarded by try/finally ), not after the with block — otherwise an exception inside the block skips it.
Write a timer_label context manager that prints a start and end line, run it inside redirect_stdout to capture everything, then report how many lines were captured.
Lesson complete — you write your own context managers!
You can build setup/cleanup logic with @contextmanager and a single yield , ignore precise errors with suppress() , capture output with redirect_stdout , manage runtime-sized resource sets with ExitStack , and adapt close()-able objects with closing() .
🚀 Up next: tempfile — create temporary files and directories that clean themselves up.
Practice quiz
What does the @contextmanager decorator turn a generator into?
- An async function
- A regular list
- A reusable context manager you can use with 'with'
- A decorator factory
Answer: A reusable context manager you can use with 'with'. @contextmanager turns a simple generator into a full context manager usable with 'with'.
In a @contextmanager generator, what does the code BEFORE the yield represent?
- The setup that runs on entering the with block
- The cleanup
- The exception handler
- Dead code
Answer: The setup that runs on entering the with block. Code before yield is the setup, running when the with block is entered.
What becomes the 'as' variable in a @contextmanager generator?
- The function name
- Always None
- The generator object
- The value passed to yield
Answer: The value passed to yield. The value yielded becomes the variable bound by 'as' in the with statement.
How many times must a @contextmanager generator yield?
- Zero times
- Exactly once
- Twice
- At least three times
Answer: Exactly once. It must yield exactly once; yielding zero or multiple times raises a RuntimeError.
What does contextlib.suppress(FileNotFoundError) do?
- Cleanly ignores that specific exception, like try/except: pass
- Raises FileNotFoundError
- Logs the error to a file
- Retries the operation
Answer: Cleanly ignores that specific exception, like try/except: pass. suppress(SomeError) swallows that specific exception so the program continues — a clean try/except: pass.
Why is 'with suppress(Exception):' considered bad practice?
- It is slower
- It only works in Python 3.11+
- It hides real bugs by swallowing everything broadly
- It raises a RuntimeError
Answer: It hides real bugs by swallowing everything broadly. Suppressing Exception broadly hides genuine bugs; suppress only the specific error you expect.
What does redirect_stdout(buffer) do?
- Deletes printed output
- Captures everything print() writes into the buffer instead of the screen
- Speeds up printing
- Redirects input from a file
Answer: Captures everything print() writes into the buffer instead of the screen. redirect_stdout(buffer) captures print() output into a string buffer like io.StringIO.
What problem does contextlib.ExitStack solve?
- Making code run in parallel
- Suppressing all output
- Replacing for-loops
- Managing a dynamic, unknown-at-write-time number of context managers
Answer: Managing a dynamic, unknown-at-write-time number of context managers. ExitStack lets you enter a runtime-determined number of context managers and clean them all up.
In what order does ExitStack exit the contexts it entered?
- The same order they were entered
- Reverse order
- Random order
- Alphabetical order
Answer: Reverse order. ExitStack exits the entered contexts in reverse order when the block ends.
What does contextlib.closing(obj) do?
- Opens a file
- Suppresses errors
- Adapts any object with a close() method into a context manager
- Creates a generator
Answer: Adapts any object with a close() method into a context manager. closing(obj) wraps an object so its close() method is called automatically at block end.