CodeNebula
Python⚡Concurrencyintermediate

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

snippet.py
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

coroutines.py
# 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())
Run command
python3 coroutines.py