Python - Asyncio
Overview
Estimated time: 30–45 minutes
asyncio enables concurrent I/O via coroutines and an event loop. Learn how to structure async code safely and avoid blocking the loop.
Learning Objectives
- Write coroutines with
async defandawait. - Run tasks concurrently and handle cancellations/timeouts.
- Recognize when to use threads/processes vs asyncio.
Prerequisites
- Functions, exceptions; basic understanding of I/O-bound vs CPU-bound work
Examples
import asyncio
async def work(name, delay):
await asyncio.sleep(delay)
return f"{name} done"
async def main():
t1 = asyncio.create_task(work("A", 1))
t2 = asyncio.create_task(work("B", 1.5))
results = await asyncio.gather(t1, t2)
print(results)
asyncio.run(main())
Expected Output:
['A done', 'B done']
Common Pitfalls
- Blocking the event loop with CPU-bound work or synchronous I/O—offload via
asyncio.to_threadorrun_in_executor. - Forgetting to handle cancellations and timeouts; use
asyncio.wait_forandtry/finallyfor cleanup. - Mixing sync and async APIs; prefer libraries with native async support.
Best Practices
- Use
asyncio.create_taskfor fire-and-forget, track tasks to avoid leaks. - Apply timeouts and cancellation handling; ensure idempotent cleanup.
- Keep coroutines small and composable; avoid deep nesting.
Checks for Understanding
- How do you run two coroutines concurrently and get both results?
- How do you offload CPU-bound work in an async app?
Show answers
- Create tasks and
await asyncio.gather(...). - Use
asyncio.to_thread(3.9+) orloop.run_in_executorwith a ThreadPool/ProcessPool.
Exercises
- Implement concurrent HTTP GETs using
aiohttp(orhttpxin async mode) with timeouts. - Demonstrate cancellation of a long-running task and proper resource cleanup.