Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Beyond opening files, Python context managers can capture printed output, ignore a specific harmless error, and clean up a variable number of resources. The standard-library contextlib module makes each pattern concise. Here’s when to use them—and the caveats that matter.

What a context manager does

A context manager gives a block of code setup and cleanup behavior. When execution enters a with block, Python calls the manager’s __enter__() method; when the block ends, Python calls __exit__(), including if an exception occurs inside it. This is why a context manager is useful for temporary changes and resources that must be cleaned up. See PEP 343 for the language behavior.

The standard-library contextlib module provides managers for common patterns. Three particularly useful examples are redirecting output, suppressing a known exception, and managing resources whose number is determined at runtime.

Capture printed output with redirect_stdout

contextlib.redirect_stdout(target) temporarily assigns sys.stdout to a file-like target. If a function prints text and you need to inspect that text rather than display it, use io.StringIO as the target:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import io
from contextlib import redirect_stdout

buffer = io.StringIO()
with redirect_stdout(buffer):
    help(pow)
text = buffer.getvalue()

The with statement can also bind the replacement stream directly. The object returned by __enter__() is the stream, so this version reads naturally when the buffer is only needed inside the block and afterward:

from contextlib import redirect_stdout
import io

with redirect_stdout(io.StringIO()) as output:
    help(pow)
text = output.getvalue()

The target can also be a file or, with an appropriate file-like object, another output destination such as sys.stderr. The key limitation is that this manager changes the process-wide sys.stdout binding. Python’s contextlib documentation therefore says it is unsuitable for most threaded applications and for library code, though it can be handy in utility scripts. For library APIs or concurrent work, prefer an explicit output stream parameter when the code supports one.

Ignore one known exception with suppress

contextlib.suppress is a compact way to express that a particular exception is harmless in one small region. For example, removing a temporary file should continue if the file has already been removed:

import os
from contextlib import suppress

with suppress(FileNotFoundError):
    os.remove("somefile.tmp")

If FileNotFoundError occurs in the block, execution resumes at the first statement after the with. Other exception types still propagate. That narrow scope is the point: suppress only an exception that is safe to ignore in this operation. Avoid broad suppression such as suppress(Exception) or a blanket except Exception, which can conceal unrelated programming errors. The official documentation likewise cautions that completely suppressing exceptions is appropriate only when silently continuing is known to be correct.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Manage a variable number of resources with ExitStack

A normal with statement is clearest when the resources are known in advance. When a list of filenames comes from user input, or some resources are optional, contextlib.ExitStack lets code enter a dynamic number of context managers while keeping their cleanup tied to one enclosing block:

from contextlib import ExitStack

with ExitStack() as stack:
    files = [stack.enter_context(open(name)) for name in filenames]
    # Process files here.

Each call to stack.enter_context() enters a manager and registers its exit behavior. When the stack closes, registered cleanup runs in reverse order. If opening a later file raises an exception, files opened earlier in the comprehension are still closed as the stack unwinds.

Use ExitStack when resources are assembled programmatically, may or may not be present, or when cleanup actions need to be registered dynamically. It can also register ordinary cleanup functions with stack.callback(); pop_all() transfers registered callbacks to a new stack, which supports all-or-nothing acquisition patterns. The contextlib documentation identifies supporting a variable number of context managers and cleanup operations in one with statement as the primary use case for ExitStack.

For a fixed set of resources visible in the code, a regular multi-item with statement or nested with blocks are usually easier to read. Choose ExitStack when the set is variable, optional, or built from data.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Can you reuse or nest a context manager?

Not necessarily. Reuse and nesting behavior depends on the manager. The contextlib documentation distinguishes single-use, reusable, and reentrant managers. A generator-based manager created with @contextmanager is normally single-use. A threading.Lock can be reused but is not reentrant; threading.RLock, suppress(), and redirect_stdout() are examples of reentrant managers.

After __exit__() has run, a single-use manager may no longer be usable, as PEP 343 cautions. Unless the manager’s documentation explicitly supports reuse, create a fresh instance for each with block.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.