Source: Asynchronous Programming in Python
Concurrent vs Parallel
- Concurrent: tasks share one thread, taking turns — NOT running at the same time
- Parallel: tasks run simultaneously on multiple CPU cores (requires
multiprocessing) - asyncio is concurrent, not parallel
Synchronous vs Async
Synchronous (normal code): each task waits for the previous to finish. Bottleneck: idle waiting (HTTP calls, file I/O, sleep, database calls).
Asynchronous (asyncio): while one task waits, the next task runs. Total CPU work is the same — less idle time.
asyncio API
Core rule
All awaitable objects must run inside an event loop.
asyncio.run()creates the top-level event loop.
Coroutines
Declared with async def. Called 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
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...")
await taskA # wait for A to finish
await taskB # wait for B to finish
asyncio.run(main())
# Output interleaved: A 3 / B 2 / Doing something else... / A 2 / B 1 / A 1 / done! / done!gather() — run multiple coroutines and wait for all
async def main():
await asyncio.gather(
countdown("A", 4),
countdown("B", 3)
)
print("Everything done!")
asyncio.run(main())Futures
- Low-level awaitable object (equivalent of a JavaScript Promise)
- Rare to use directly — asyncio handles them internally
Awaitable Objects Summary
| Type | Description |
|---|---|
| Coroutine | async def function — awaited with await |
| Task | Scheduled coroutine — created with asyncio.create_task() |
| Future | Low-level — rarely used directly |
Key Pattern for IoT
Use asyncio to concurrently handle:
- Reading from sensor
- Publishing to MQTT
- Listening for commands
async def read_sensor():
while True:
value = sensor.read()
await asyncio.sleep(5)
async def publish_mqtt():
while True:
await client.publish(topic, payload)
await asyncio.sleep(5)
asyncio.run(asyncio.gather(read_sensor(), publish_mqtt()))See Also
- Asyncio concept
- Async Python topic