Running Tasks Concurrently with asyncio
Python's asyncio
module enables you to run code concurrently, which is particularly useful for I/O-bound operations like reading from sensors, fetching data, or controlling devices.
This approach allows multiple tasks to run without blocking each other, similar to executing multiple subroutines in parallel.
Key Concepts
async
Functions: Defined usingasync def
, these functions can pause and resume their execution, allowing other tasks to run during the pause.await
Keyword: Used withinasync
functions to pause execution until the awaited task completes, during which other tasks can proceed.- Event Loop: The core component that manages and schedules the execution of asynchronous tasks.
Example 1: Basic Asynchronous Task
Here's a simple example to demonstrate asynchronous execution:
import asyncio
async def say_hello():
print("Hello!")
await asyncio.sleep(1) # Simulate a delay
print("World!")
async def main():
await asyncio.gather(say_hello(), say_hello()) # Run both tasks concurrently
asyncio.run(main())
Explanation
asyncio.sleep(1)
: Pauses the function for 1 second without blocking other tasks.asyncio.gather()
: Runs multiple asynchronous functions concurrently.
Example 2: Running Multiple I/O Operations
Let's simulate running several I/O tasks concurrently:
import asyncio
async def read_sensor(sensor_id):
print(f"Reading sensor {sensor_id}...")
await asyncio.sleep(2) # Simulate sensor delay
print(f"Sensor {sensor_id} data received!")
async def main():
tasks = [read_sensor(i) for i in range(3)]
await asyncio.gather(*tasks) # Run all sensor reads concurrently
asyncio.run(main())
Explanation
- Multiple
read_sensor()
calls: Simulates reading from three sensors concurrently. await asyncio.gather()
: Runs all sensor reads concurrently, reducing total execution time compared to sequential execution.
Summary
asyncio
allows you to run coroutines (asynchronous functions) concurrently. The event loop manages the execution of these coroutines, allocating runtime during await
periods.