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.