Async Python

Concurrent vs Parallel

TermMeaningPython tool
ConcurrentTasks share ONE thread, taking turns — NOT simultaneousasyncio
ParallelTasks run simultaneously on multiple CPU coresmultiprocessing

asyncio is concurrent, not parallel.

Total CPU work is the same — concurrency eliminates idle waiting time (HTTP calls, file I/O, sleep, database calls).

Sync vs Async

Synchronous (normal code):

Task A: [work][WAIT for IO][work][done]
Task B:                                [work][WAIT for IO][work][done]
Time: ──────────────────────────────────────────────────────────────►

Asynchronous (asyncio):

Task A: [work][·····wait·····][work][done]
Task B:       [work][···wait···][work][done]
Time: ──────────────────────────────────────────────────────────────►

Core Rule

All awaitable objects must run inside an event loop. asyncio.run() creates the top-level event loop.

asyncio API

Coroutines (async def)

Declared with async def. Call with await or asyncio.run().

import asyncio
 
async def countdown(name, seconds):
    for i in range(seconds, 0, -1):
        print(name, i)
        await asyncio.sleep(1)   # yields to event loop — other tasks can run
    print("done!")
 
async def main():
    await countdown("simple", 4)
 
asyncio.run(main())
# Output: simple 4 / simple 3 / simple 2 / simple 1 / done!

Tasks — Concurrent Execution

asyncio.create_task() schedules a coroutine to run concurrently. Must be awaited to ensure it completes.

async def main():
    taskA = asyncio.create_task(countdown("A", 3))
    taskB = asyncio.create_task(countdown("B", 2))
 
    await asyncio.sleep(1)
    print("Doing something else while A and B run...")
 
    await taskA   # wait for A to finish
    await taskB   # wait for B to finish
 
asyncio.run(main())
# Output: A 3 / B 2 / Doing something else... / A 2 / B 1 / A 1 / done! / done!

gather() — Run Multiple Coroutines, Wait for All

async def main():
    await asyncio.gather(
        countdown("A", 4),
        countdown("B", 3)
    )
    print("Everything done!")
 
asyncio.run(main())

Awaitable Objects Summary

TypeDescriptionCreated by
Coroutineasync def functioncalling async def func
TaskScheduled coroutineasyncio.create_task()
FutureLow-level promiserarely used directly

IoT Pattern — Concurrent Sensor/MQTT Loop

import asyncio
 
async def read_sensor():
    while True:
        value = sensor.read()
        print(f"Sensor: {value}")
        await asyncio.sleep(5)
 
async def publish_mqtt():
    while True:
        await client.publish(topic, payload)
        await asyncio.sleep(5)
 
async def listen_commands():
    while True:
        cmd = await client.receive()
        handle(cmd)
 
# Run all concurrently
asyncio.run(asyncio.gather(
    read_sensor(),
    publish_mqtt(),
    listen_commands()
))

See Also