A Python context manager defines what happens when execution enters and leaves a with block. It is commonly used to acquire a resource before the block and release it afterward, including when the block raises an exception. The two main ways to create one are implementing __enter__ and __exit__ on a class, or using @contextmanager to wrap setup and cleanup around a generator’s single yield.
What a context manager does
A context manager establishes a runtime context for a with statement. It can manage files, locks, temporary state, and other operations that need a defined beginning and end. For example, with open(path) as file: gives the file a clear lifetime: Python opens it, the block uses it, and the file is closed when the block exits.
As an Amazon Associate I earn from qualifying purchases.
The Python Language Reference says, “The with statement guarantees that if the __enter__() method returns without an error, then __exit__() will always be called.” This guarantee covers normal completion and exceptions raised inside the block; it does not apply if entry itself fails. Python Language Reference: The with statement.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →What Python does during a with statement
For with expression as target:, Python evaluates the expression, gets the manager’s __enter__ and __exit__ methods, and calls __enter__. If an as target is present, it receives the value returned by __enter__. Python then runs the block and calls __exit__ as the block leaves.
#1 Best Overall
- If the block completes normally,
__exit__receivesNonefor the exception type, value, and traceback. - If the block raises an exception,
__exit__receives information about it. A truthy return value suppresses the exception; a false value orNonelets it propagate.
Cleanup and error handling are separate decisions: a manager can release a resource in __exit__ while still allowing the original exception to reach the caller. Multiple managers in one with statement behave like nested with statements, so their exits happen in reverse order of entry. Python Language Reference: The with statement.
Implementing a manager with a class
A class-based manager implements __enter__ and __exit__. Return from __enter__ the value that the block should use. Put cleanup in __exit__, and return a truthy value only when the manager deliberately handles and suppresses the block’s exception.
Rank #2
class ManagedValue:
def __enter__(self):
self.value = acquire_resource()
return self.value
def __exit__(self, exc_type, exc_value, traceback):
release_resource(self.value)
# None means an exception from the block is not suppressed.
This illustrative example leaves acquire_resource and release_resource to the application. In real code, consider what should happen if acquisition fails, or if cleanup itself raises; the context manager protocol does not make those application-specific choices for you. The with statement looks up these special methods implicitly, so callers use the manager rather than invoking its methods directly. Python Language Reference: The with statement.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Writing a manager with @contextmanager
contextlib.contextmanager lets a generator function provide the same entry-and-exit structure without a class. Put setup before yield, the value to bind after as in the yield expression, and cleanup in a finally block.
from contextlib import contextmanager
@contextmanager
def managed_resource():
resource = acquire_resource()
try:
yield resource
finally:
release_resource(resource)
with managed_resource() as resource:
use(resource)
The generator must yield exactly once. The code before the yield runs when entering the block; the code after it runs as the block exits. If the block raises an exception that is not suppressed, the exception is thrown back into the generator at the yield point. If you catch it only to log or perform another action, re-raise it unless suppression is intentional; otherwise the generator manager treats it as handled. Python contextlib documentation: contextmanager.
Class-based or generator-based: which should you use?
| Consideration | Class-based manager | @contextmanager |
|---|---|---|
| Natural fit | Entry and exit are clearer as distinct methods. | Setup, one block of use, and cleanup fit neatly around one yield. |
| State and branching | Useful when the manager must retain substantial state or has complex behavior across entry and exit. | Often compact for straightforward setup and cleanup. |
| Exception handling | The exception information is explicit in the __exit__ parameters. |
Exceptions are raised at the yield point; catch and re-raise if they should not be suppressed. |
| Reuse and async behavior | Reuse or reentrancy must be designed for the particular manager; async work requires the asynchronous protocol. | A manager created by the decorator is single-use; asynchronous generator contexts use @asynccontextmanager. |
Neither pattern is universally preferable. Choose the one that makes the manager’s lifetime and exception behavior easiest to understand. Python contextlib documentation: contextmanager.
Useful tools in contextlib
closing for objects with a close() method
closing(obj) calls obj.close() when the block exits. It can adapt an object that has a close method but lacks context-manager support. Prefer the object’s native manager when available; for example, the documentation notes that urlopen() already supports with, so wrapping it in closing() is unnecessary. Python contextlib documentation: closing.
nullcontext for an optional manager
nullcontext(value) does nothing on exit and returns value from entry. It can simplify a function that accepts either an already-open resource or a path from which it should open a resource, allowing both cases to share a with block. Python contextlib documentation: nullcontext.
Best Value
suppress for specific exceptions
suppress(SomeSpecificError) suppresses only the exception types listed. Use it only when continuing after those errors is known to be correct, rather than as a broad way to hide failures. Python contextlib documentation: suppress.
ExitStack for a dynamic number of contexts
ExitStack manages contexts and callbacks registered at runtime and unwinds them in reverse registration order, like nested with statements. It is useful when the number of resources is not known in advance, or when later acquisition might fail after earlier resources have already been acquired. Python contextlib documentation: ExitStack.
Asynchronous context managers
Use async with when setup or cleanup must perform asynchronous work. The asynchronous protocol uses __aenter__ and __aexit__; contextlib.asynccontextmanager provides a generator-based option. These are distinct from the synchronous with, __enter__/__exit__, and @contextmanager protocol. Python contextlib documentation: asynccontextmanager.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Repair Windows errors before they cause bigger problems3Scan for outdated or missing drivers - takes under a minuteReuse, reentrancy, and Python versions
Do not assume every manager can be reused or entered recursively. The Python documentation says most context managers are single-use and specifically notes that file objects and managers created by @contextmanager should be recreated for each use. Whether a manager is reusable or reentrant depends on that particular manager. Python contextlib documentation: reusable context managers.
The current official documentation is for Python 3.14.8, and individual helpers have their own version histories. If code must run on older Python releases, check the documentation for the exact helper and version you need rather than assuming every contextlib feature is available everywhere. Python contextlib documentation.
Quick Recap
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.




