Python Mastery · Chapter 9 · ~22 min · Advanced
Asyncio & the Event Loop Race Track
Why wait 10 seconds for 5 API calls when you can finish all of them in 2 seconds? Master Python's event loop, async / await, and high-concurrency non-blocking architecture.
- Explain the event loop in plain words
- Write async / await coroutines
- Spot blocking calls that freeze everything
- Run tasks concurrently with gather
1The Waiting Game: Why Async Matters
In typical web development, your CPU spends 99% of its time doing nothing: waiting for database queries, network APIs, or disk reads.
Synchronous code sits and blocks like someone waiting in line. Asynchronous code places an order, steps aside to serve the next customer, and comes back when the food is ready.
Fetch User (1.5s), Fetch Orders (1.0s), Fetch Notifications (0.8s)
2Coroutines and the 'await' Keyword
When you prefix a function with async def, it becomes a coroutine. When you call it, Python pauses and gives you an unstarted promise. The await keyword is how you hand control over to the event loop.
async def without awaitIn normal Python, calling f() executes code. In async Python, calling f() merely builds a coroutine object!
async def get_price(item):
await asyncio.sleep(1)
return 49.99
# In your main function:
price = get_price("laptop") # ⚠️ No await!
print(price)What does calling an async def function do on its own?
3The Mental Model: Chefs, Timers, and Cores
Is Asyncio multithreading? No! Asyncio uses a single thread with cooperative multitasking. Compare the three concurrency models below:
How Python handles concurrency vs. parallelism.
The chef puts pasta into boiling water, sets a 10-minute timer, and doesn't stand there staring at the pot. While the water boils, the chef chops tomatoes, seasons garlic, and kneads dough.
4The Async Killer: Blocking Calls
Because the event loop runs on one thread, any synchronous blocking function stops all other coroutines from ticking. Never call time.sleep() or synchronous requests.get() inside async functions!
The event loop runs on a single thread. If you call synchronous blocking functions like time.sleep() or requests.get(), you freeze everyone!
# IDIOMATIC ASYNC:
import asyncio
async def worker():
# Yields control back to event loop!
await asyncio.sleep(2) # ⏩ Other tasks keep running!await asyncio.sleep registers a timer callback with the event loop and yields the CPU immediately. 10,000 other tasks can run in those 2 seconds.
Mental model
One chef, many timers
The event loop is one chef. await asyncio.sleep(2) sets a timer and the chef cooks something else. time.sleep(2) makes the chef stand frozen staring at the oven — every other dish waits too. Same with requests.get() inside async def; use httpx.AsyncClient instead.
Inside async def, which call freezes ALL other tasks?
5Concurrent Orchestration: gather and TaskGroup
To fire multiple requests at the exact same time, use asyncio.gather() or Python 3.11's TaskGroup:
# Modern Python 3.11+ Structured Concurrency:
async with asyncio.TaskGroup() as tg:
task1 = tg.create_task(fetch_user(user_id))
task2 = tg.create_task(fetch_orders(user_id))
task3 = tg.create_task(fetch_settings(user_id))
# When the block exits, all 3 tasks have finished cleanly!
print(task1.result(), task2.result(), task3.result())6Challenge: Asyncio Race Engineer
Test your understanding of the event loop, coroutines, non-blocking I/O, and concurrency pitfalls. Score 5/5 to complete Chapter 9!
Asyncio & the Event Loop Race Track · code lab
Edit the example, run it with Python, or step through the lines.
1import asyncio23async def fetch(name, delay):4 await asyncio.sleep(delay)5 return f"{name} ready"67results = await asyncio.gather(fetch("A", 0.01), fetch("B", 0.01))8print(results)
Python output
Run the code to see its output.
1.What happens if you call an 'async def' function without 'await'?
2.What is the primary danger of calling time.sleep() inside an async function?
3.Which function is used to run multiple async coroutines concurrently and wait for all of them to finish?
4.When is Asyncio the ideal architectural choice over Multiprocessing?
5.In modern Python (3.11+), what is the recommended context manager for running concurrent tasks safely with error bubbling?
Run and measure the concurrent API aggregator in the Python Playground (code preloaded).
7Recap
- Event Loop: A cooperative single-threaded scheduler that juggles I/O tasks while they wait.
- async def: Returns a coroutine object; it will not execute until awaited or scheduled.
- await: Pauses the current coroutine and yields execution back to the loop.
- Never Block: Use
asyncio.sleep()andhttpx/aiohttp, nevertime.sleep()orrequests. - asyncio.gather / TaskGroup: Run multiple coroutines concurrently and bundle results cleanly.
Finish the challenge above to complete the chapter, or