Async Programming
Write concurrent I/O-bound code with asyncio coroutines, tasks, and structured concurrency.
async and await
async def defines coroutines awaited with await. await suspends the coroutine until the awaited operation completes without blocking other coroutines on the event loop.
Use asyncio.run(main()) as the entrypoint in scripts. In frameworks like FastAPI, the loop is managed for you.
Do not call blocking I/O inside coroutines without to_thread or executors—it stalls the entire loop.
- Use asyncio.gather for parallel independent coroutines
- Set timeouts with asyncio.wait_for
- Install uvloop on Linux for performance when compatible
async def fetch(session, url):
async with session.get(url) as resp:
return await resp.json()
async def main():
async with aiohttp.ClientSession() as session:
return await fetch(session, "https://api.example.com")Tasks and the Event Loop
asyncio.create_task schedules coroutines concurrently. Tasks can be cancelled with task.cancel() during shutdown or user abort.
The event loop runs coroutines cooperatively. Long CPU work belongs in ProcessPoolExecutor, not the loop thread.
Async context managers (async with) acquire connections and locks without blocking peers.
- Await all tasks before closing the loop
- Handle CancelledError during graceful shutdown
- Use asyncio.Semaphore to limit concurrent API calls