Asynchronous Python & Concurrent I/O (asyncio)
Unlock high-throughput backend performance. Master async def, await, asyncio.gather(), httpx, and AsyncSession for non-blocking I/O operations.
Blocking Synchronous Execution vs Non-Blocking Asynchronous Event Loop
Synchronous code forces the CPU to sit idle waiting for DB/API responses. Asynchronous `await` yields control so other concurrent tasks process immediately.
# ❌ Thread blocks sequentially for 500ms
def get_user(user_id: int):
user = database.fetch_user(user_id) # Blocks CPU!
return user
# ✅ Yields control to event loop during I/O wait
async def get_user(user_id: int):
user = await database.fetch_user(user_id)
return user
⚡ The asyncio Event Loop Workflow
🛠️ Essential Async Python Primitives
async def / await
Keywords defining coroutines and declaring non-blocking pause points.
asyncio.gather(*tasks)
Fires multiple coroutine tasks concurrently in parallel batches.
httpx.AsyncClient()
Modern non-blocking HTTP client replacing legacy synchronous `requests`.
AsyncSession (SQLAlchemy)
Async database sessions executing SQL queries without blocking threads.
💻 Production Blueprint: Concurrent Async HTTP Fetcher
Observe how `asyncio.gather()` processes 5 remote API queries concurrently in ~100ms instead of 500ms.
import asyncio
import httpx
async def fetch_user_data(client: httpx.AsyncClient, user_id: int) -> dict:
response = await client.get(f"https://api.example.com/users/{user_id}")
return response.json()
async def fetch_all_users_concurrently(user_ids: list[int]) -> list[dict]:
async with httpx.AsyncClient() as client:
tasks = [fetch_user_data(client, uid) for uid in user_ids]
results = await asyncio.gather(*tasks) # Concurrent execution!
return results
# Entrypoint to run event loop
profiles = asyncio.run(fetch_all_users_concurrently([101, 102, 103]))