On this page
Async Python
Why Async?
Async I/O lets a single thread handle many concurrent operations — ideal for web servers, API clients, and database connections where tasks spend time waiting.
Basic asyncio
import asyncio
async def fetch_data(name, delay):
print(f"Fetching {name}...")
await asyncio.sleep(delay)
return f"{name} done"
async def main():
result = await fetch_data("users", 2)
print(result)
asyncio.run(main())
Running Multiple Tasks
async def main():
results = await asyncio.gather(
fetch_data("users", 2),
fetch_data("orders", 1),
fetch_data("products", 3),
)
print(results) # all three complete in ~3s, not 6s
asyncio.run(main())
Async Context Managers
import aiohttp
async def fetch_url(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.text()
Async Generators
async def stream_items():
for i in range(5):
await asyncio.sleep(0.5)
yield i
async def main():
async for item in stream_items():
print(item)
When to Use Async
| Good for | Not good for |
|---|---|
| HTTP/API calls | CPU-bound computation |
| Database queries | Image/video processing |
| WebSocket servers | Heavy numerical work |
For CPU-bound tasks, use multiprocessing or concurrent.futures.ProcessPoolExecutor instead.
FastAPI Example
from fastapi import FastAPI
app = FastAPI()
@app.get("/users/{user_id}")
async def get_user(user_id: int):
user = await db.fetch_user(user_id) # non-blocking DB call
return user
Async Python is essential for modern web backends and high-concurrency services.
asyncio.create_task
Fire-and-forget or concurrent tasks without blocking:
async def main():
task1 = asyncio.create_task(fetch_data("users", 2))
task2 = asyncio.create_task(fetch_data("orders", 1))
await task1
await task2
asyncio.wait_for Timeout
try:
result = await asyncio.wait_for(fetch_data("slow-api", 30), timeout=5.0)
except asyncio.TimeoutError:
print("Request timed out")
Semaphore for Rate Limiting
sem = asyncio.Semaphore(10) # max 10 concurrent requests
async def fetch_limited(url):
async with sem:
return await fetch_url(url)
Running Sync Code in Async Context
import asyncio
def cpu_heavy():
return sum(i * i for i in range(10_000_000))
async def main():
result = await asyncio.to_thread(cpu_heavy)
print(result)
Use asyncio.to_thread() (Python 3.9+) to avoid blocking the event loop.
Debugging Async Code
import asyncio
asyncio.run(main(), debug=True) # warns about slow callbacks
Enable debug mode during development to catch unawaited coroutines.