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.