Async Python
Concurrent vs Parallel
| Term | Meaning | Python tool |
|---|---|---|
| Concurrent | Tasks share ONE thread, taking turns — NOT simultaneous | asyncio |
| Parallel | Tasks run simultaneously on multiple CPU cores | multiprocessing |
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
| Type | Description | Created by |
|---|---|---|
| Coroutine | async def function | calling async def func |
| Task | Scheduled coroutine | asyncio.create_task() |
| Future | Low-level promise | rarely 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
- Asyncio concept
- Python Essentials topic
- async-python source