Python Asynchronous Context Managers
Learn async with and asynchronous context managers through __aenter__() and __aexit__(), including awaited entry and exit, cleanup, exception handling, and multiple contexts.
Intermediate
An asynchronous context manager controls a runtime context when entering or leaving may need to suspend. Python uses async with for this form of resource or state management. The protocol is built around __aenter__() and __aexit__(), which return awaitables.
async with enters and exits an asynchronous context
An async with statement is the asynchronous counterpart to with. It evaluates the context manager, awaits __aenter__(), runs the block, and later awaits __aexit__(). The optional as target receives the value produced by __aenter__().
Output
Ready to run.
Entry and exit can suspend
The point of the asynchronous protocol is that entering and leaving the context can await other asynchronous work. An async def __aenter__() returns a coroutine, so async with awaits it before the block starts. An async def __aexit__() likewise returns a coroutine that async with awaits during cleanup.
Output
Ready to run.
as receives the awaited entry value
In async with Manager() as value, the name value does not receive an unawaited coroutine. Python awaits __aenter__() first, and the resulting value is assigned to the as target.
Output
Ready to run.
__aexit__ still runs when the block raises
After a successful __aenter__(), Python awaits __aexit__() when the async with block finishes. If the block raises, the exception type, value, and traceback are supplied to __aexit__(). Returning a false value allows the exception to propagate.
Output
Ready to run.
__aexit__ can suppress an exception
As with ordinary context managers, an asynchronous __aexit__() can suppress an exception by returning a true value. Suppression should be deliberate because it changes normal exception propagation.
Output
Ready to run.
Multiple asynchronous contexts nest
You can place multiple context-manager items in one async with statement. Python processes them like nested async with statements, so contexts enter from left to right and exit in reverse order.
Output
Ready to run.
async with belongs inside a coroutine
The async with statement is asynchronous syntax, so Python only permits it in the body of a coroutine function. At the top level of a normal module, it is a SyntaxError.
Output
Ready to run.
async with needs the asynchronous protocol
A normal context manager that only defines __enter__() and __exit__() is not automatically an asynchronous context manager. async with looks for __aenter__() and __aexit__(). This keeps synchronous cleanup and asynchronous cleanup as distinct protocols.
Output
Ready to run.
Quick check
Quick check
Which declaration gives this context manager an asynchronous entry method that async with can await?
class Manager:
async def __aexit__(self, exc_type, exc_value, traceback):
return False
Thanks for your feedback.
Mark this learning resource complete to track your learning progress.