Recipe / Python
Python asyncio primer
A short, practical walk through Python's asyncio module — event loops, coroutines, and structured concurrency. Use this as a launching pad when wiring high-throughput Meridian workers that fan out network calls without blocking the main thread.
1Coroutines, not threads
A coroutine is a function declared with async def. Calling it returns a coroutine object — it does not run yet. The event loop schedules execution, and await hands control back so other tasks can progress while you wait on I/O.
2Gather fans out, awaits all
asyncio.gather schedules multiple coroutines concurrently and resolves to the list of their results in input order. Use it when you have a known, bounded set of awaitables — e.g. three HTTP fetches that should overlap rather than serialize.
3Run with asyncio.run
asyncio.run(main()) is the canonical entrypoint — it creates a fresh loop, runs the coroutine to completion, and tears the loop down cleanly. Do not call it from inside another running loop; use await there.
import asyncio
async def fetch(name: str, delay: float) -> str:
await asyncio.sleep(delay)
return f"{name} done after {delay}s"
async def main() -> None:
results = await asyncio.gather(
fetch("alpha", 0.4),
fetch("beta", 0.2),
fetch("gamma", 0.6),
)
for r in results:
print(r)
if __name__ == "__main__":
asyncio.run(main())