Coroutines and `async`/`await`
Python · Concurrency · Run with python3
Explanation
A coroutine is a function defined with `async def` that returns a coroutine object when called (it does not run immediately). `await expr` suspends the coroutine until the awaitable (coroutine, `Task`, or `Future`) completes. `async for` iterates an async iterable; `async with` uses an async context manager. `asyncio.create_task()` schedules a coroutine as a background task — unlike `await`, the caller continues without waiting.
Real-World Scenario
A data ingestion pipeline: `async for record in async_db_cursor:` streams rows from a database without loading the full result set. Each `await` on the cursor gives the event loop a chance to run other coroutines — the pipeline stays responsive while waiting for slow DB rows. ```python import asyncio async def slow_operation(name: str, delay: float) -> str: print(f" Starting {name}") await asyncio.sleep(delay) print(f" Finished {name}") return f"{name}: done" async def sequential() -> None: # Each await blocks until completion — total ≈ 0.3 + 0.2 + 0.1s r1 = await slow_operation("A", 0.3) r2 = await slow_operation("B", 0.2) r3 = await slow_operation("C", 0.1) print([r1, r2, r3]) async def concurrent() -> None: # All three run concurrently — total ≈ max(0.3, 0.2, 0.1)s t1 = asyncio.create_task(slow_operation("X", 0.3)) t2 = asyncio.create_task(slow_operation("Y", 0.2)) t3 = asyncio.create_task(slow_operation("Z", 0.1)) results = await asyncio.gather(t1, t2, t3) print(results) print("=== Sequential ===") asyncio.run(sequential()) print("\n=== Concurrent ===") asyncio.run(concurrent()) ```
Quick Snippet
import asyncio
async def slow_operation(name: str, delay: float) -> str:
print(f" Starting {name}")
await asyncio.sleep(delay)
print(f" Finished {name}")
return f"{name}: done"
async def sequential() -> None:
# Each await blocks until completion — total ≈ 0.3 + 0.2 + 0.1s
r1 = await slow_operation("A", 0.3)
r2 = await slow_operation("B", 0.2)
r3 = await slow_operation("C", 0.1)
print([r1, r2, r3])
async def concurrent() -> None:
# All three run concurrently — total ≈ max(0.3, 0.2, 0.1)s
t1 = asyncio.create_task(slow_operation("X", 0.3))
t2 = asyncio.create_task(slow_operation("Y", 0.2))
t3 = asyncio.create_task(slow_operation("Z", 0.1))
results = await asyncio.gather(t1, t2, t3)
print(results)
print("=== Sequential ===")
asyncio.run(sequential())
print("\n=== Concurrent ===")
asyncio.run(concurrent())Full Example
# Compile: python3 coroutines.py
# Output:
# === Sequential ===
# === Concurrent ===
import asyncio
async def slow_operation(name: str, delay: float) -> str:
await asyncio.sleep(delay)
return f"{name}: done"
async def sequential() -> None:
import time
start = time.perf_counter()
r1 = await slow_operation("A", 0.05)
r2 = await slow_operation("B", 0.03)
r3 = await slow_operation("C", 0.02)
elapsed = time.perf_counter() - start
print(f"Sequential: {[r1, r2, r3]} ({elapsed:.3f}s)")
async def concurrent() -> None:
import time
start = time.perf_counter()
t1 = asyncio.create_task(slow_operation("X", 0.05))
t2 = asyncio.create_task(slow_operation("Y", 0.03))
t3 = asyncio.create_task(slow_operation("Z", 0.02))
results = await asyncio.gather(t1, t2, t3)
elapsed = time.perf_counter() - start
print(f"Concurrent: {results} ({elapsed:.3f}s)")
print("=== Sequential ===")
asyncio.run(sequential())
print("\n=== Concurrent ===")
asyncio.run(concurrent())
python3 coroutines.py