async and await with asyncio
Intuition
A web server spends most of its time waiting — for a database, another API, a file. While one
request waits, the server could work on another. async/await lets one thread juggle many
waiting tasks: at every await, a task says "I am waiting; run someone else", and the
event loop switches to another ready task.
Precise explanation
import asyncio
async def worker(name, log): # a coroutine function
log.append(f"{name} start")
await asyncio.sleep(0) # yield control to the event loop
log.append(f"{name} end")
return name.upper()
asyncio.run(worker("a", [])) # run a coroutine from normal code
- Calling
worker(...)does not run it; it creates a coroutine object. It runs when awaited or scheduled. await a(); await b()runs them one after the other.await asyncio.gather(a(), b())runs them concurrently and returns results in argument order, regardless of which finished first. With theworkerabove the log becomesa start, b start, a end, b end— eachawaitlet the other task proceed.asyncio.Semaphore(n)limits how many tasks enter a block at once:async with sem: ....await asyncio.wait_for(coro, timeout)raisesTimeoutError(asyncio.TimeoutError, the same class since Python 3.11) if it takes too long and cancels the work.- Blocking calls such as
time.sleepfreeze the whole loop; useawait asyncio.sleepand async libraries inside coroutines.
Worked example
Three downloads of 1 s each: sequential awaits take about 3 s; gather takes about 1 s, because
the waits overlap. (Tests in this site avoid real time and check the order of events instead.)
Common mistakes
- Forgetting
await, so the coroutine never runs (Python warns "coroutine was never awaited"). - Calling
asyncio.runinside code that is already running in an event loop. - Expecting
asyncto speed up CPU-heavy work — it only overlaps waiting.
Why this matters
FastAPI runs async def endpoints on an event loop (FA-14), and ASGI applications
(FA-07) are coroutines.
References
- Coroutines and Tasks (asyncio) — Python Software Foundation (
S061) - FastAPI: Concurrency and async / await — FastAPI (Sebastián Ramírez) (
S077)