liveBook · Manning

Async with

As explained in Python Concurrency with asyncio

async with is Python syntax for asynchronously entering and exiting a context manager around a block of code.

async with asynchronously acquires a resource, runs a block, and releases the resource when the block ends. It provides the coroutine-aware counterpart to synchronous with, including cleanup when an exception occurs. section 4.2

Use async with when a resource must be acquired or released through awaitable operations:

  • Implement asynchronous context managers with async __aenter__ and async __aexit__ methods. section 4.2
  • Bind the value returned by __aenter__ with as, then use it inside the indented block. section 4.2
  • Let __aexit__ perform cleanup automatically after normal completion or an exception. section 4.2
  • Prefer async with for asyncio locks; leaving the block releases the lock and lets another coroutine enter the critical section. section 11.2

HTTP sessions and database connections

aiohttp uses async with for both a ClientSession and an individual request: a session can be reused for connection pooling, while the response is processed inside the request block. asyncpg uses the same pattern for connection pools and pool.acquire(); the acquired connection returns to the pool when the block ends. Without that release, concurrent queries can exhaust the pool and wait indefinitely. section 4.2.1 section 5.5.2

Listing 4.1 An asynchronous context manager to wait for a client connection
import asyncio
import socket
from types import TracebackType
from typing import Optional, Type
 
 
class ConnectedSocket:
 
    def __init__(self, server_socket):
        self._connection = None
        self._server_socket = server_socket
 
    async def __aenter__(self):                                      #1
        print('Entering context manager, waiting for connection')
        loop = asyncio.get_event_loop()
        connection, address = await loop.sock_accept(self._server_socket)
        self._connection = connection
        print('Accepted a connection')
        return self._connection
 
    async def __aexit__(self,
                        exc_type: Optional[Type[BaseException]],
                        exc_val: Optional[BaseException],
                        exc_tb: Optional[TracebackType]):            #2
        print('Exiting context manager')
        self._connection.close()
        print('Closed connection')
 
 
async def main():
    loop = asyncio.get_event_loop()
 
    server_socket = socket.socket()
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server_address = ('127.0.0.1', 8000)
    server_socket.setblocking(False)
    server_socket.bind(server_address)
    server_socket.listen()
 
    async with ConnectedSocket(server_socket) as connection:         #3
        data = await loop.sock_recv(connection, 1024)
        print(data)                                                  #4
 
 
asyncio.run(main())

Shows a complete asynchronous context manager that awaits a socket connection in __aenter__, exposes it inside async with, and closes it in __aexit__. section 4.2

How Python Concurrency with asyncio covers it

How deep it goes
Explains the async context-manager protocol, cleanup behavior, and practical resource-pool usage without examining interpreter internals.
Examples
Demonstrates socket acceptance, aiohttp requests, asyncpg pools, acquired database connections, and asyncio locks.
What it assumes
Assumes coroutines and awaitable operations while contrasting async with against synchronous with and try/finally cleanup.
What you can do after
Builds asynchronous context managers and safely operates HTTP, database, socket, and lock resources with automatic release.
How it connects
Connects asynchronous context managers with coroutines, resource cleanup, connection pooling, HTTP requests, database connections, and asyncio locks.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Python Concurrency with asyncio. The section links point to the parts of the book it draws on.