Phase 1 — Foundations · Lesson 7 · 20 XP
Async Python: asyncio and concurrency
async and await let your program start a slow operation — like waiting for a network response — and let other work run while it waits, instead of blocking. This only helps for I/O-bound work (waiting on the network, disk, or another service). It does nothing for CPU-bound work like a tight math loop, because the CPU is still busy the whole time.
import asyncio, httpx
async def fetch(client, url):
r = await client.get(url)
return r.status_code
async def main():
async with httpx.AsyncClient() as client:
results = await asyncio.gather(*(fetch(client, u) for u in urls))
asyncio.run(main())asyncio.gather runs a batch of coroutines concurrently and waits for all of them — fetching 50 URLs this way takes roughly as long as the slowest one, not the sum of all 50. A plain for loop with await inside it runs them one at a time, sequentially, gaining nothing from async at all.
Exercise
Fetch 50 URLs concurrently using httpx.AsyncClient and asyncio.gather, and time it against a plain sequential for loop doing the same requests. Confirm the concurrent version is dramatically faster.
Check yourself
1. Why does async speed up I/O-bound work like HTTP calls but do nothing for CPU-bound work?
2. What does asyncio.gather do that a for loop with await inside it doesn't?
HTTP fundamentals: requests, status codes, JSON, httpx
Answer the check-yourself questions to unlock this