Python asyncio
Module: Detailed Overview and Examples
The asyncio
module in Python provides support for asynchronous programming by using coroutines, tasks, and event loops. It allows you to write concurrent code using the async
and await
syntax, making it easier to handle tasks that involve I/O operations, networking, and other asynchronous activities.
Importing the asyncio
Module
To use the functions and classes from the asyncio
module, you need to import it:
Key Components
1. Event Loop
The event loop is the core component of asyncio
that manages and executes asynchronous tasks.
Example
import asyncio
# Define an asynchronous function
async def hello_world():
print("Hello")
await asyncio.sleep(1)
print("World")
# Run the event loop
asyncio.run(hello_world())
2. Coroutines
Coroutines are functions defined with the async def
syntax. They use await
to yield control to the event loop.
Example
import asyncio
# Define a coroutine
async def greet(name):
print(f"Hello, {name}!")
await asyncio.sleep(1)
print(f"Goodbye, {name}!")
# Run the coroutine
asyncio.run(greet("Alice"))
3. Tasks
Tasks are used to schedule coroutines to run concurrently. They are created using asyncio.create_task()
or loop.create_task()
.
Example
import asyncio
async def task1():
print("Task 1 start")
await asyncio.sleep(2)
print("Task 1 end")
async def task2():
print("Task 2 start")
await asyncio.sleep(1)
print("Task 2 end")
# Run multiple tasks concurrently
async def main():
await asyncio.gather(task1(), task2())
asyncio.run(main())
4. asyncio.gather()
asyncio.gather()
is used to run multiple coroutines concurrently and wait for them to complete.
Example
import asyncio
async def fetch_data(x):
print(f"Fetching data {x}")
await asyncio.sleep(x)
return f"Data {x}"
async def main():
results = await asyncio.gather(fetch_data(2), fetch_data(1))
print(results)
asyncio.run(main())
5. asyncio.sleep()
asyncio.sleep()
is a coroutine that pauses execution for a given number of seconds.
Example
import asyncio
async def delay_print():
print("Start")
await asyncio.sleep(2)
print("End")
asyncio.run(delay_print())
6. asyncio.Queue
asyncio.Queue
provides a FIFO queue for coroutines, allowing safe concurrent access.
Example
import asyncio
async def producer(queue):
for i in range(5):
await asyncio.sleep(1)
await queue.put(i)
print(f"Produced {i}")
async def consumer(queue):
while True:
item = await queue.get()
if item is None:
break
print(f"Consumed {item}")
await asyncio.sleep(2)
async def main():
queue = asyncio.Queue()
await asyncio.gather(producer(queue), consumer(queue))
asyncio.run(main())
7. Exception Handling
Handling exceptions in asynchronous code is similar to synchronous code but should be done using try
and except
within coroutines.
Example
import asyncio
async def error_task():
try:
await asyncio.sleep(1)
raise ValueError("An error occurred")
except ValueError as e:
print(f"Caught exception: {e}")
asyncio.run(error_task())
8. asyncio.Event
asyncio.Event
is a simple synchronization primitive that allows coroutines to wait for an event to be set.
Example
import asyncio
async def waiter(event):
print("Waiting for event")
await event.wait()
print("Event received")
async def setter(event):
print("Setting event")
await asyncio.sleep(2)
event.set()
async def main():
event = asyncio.Event()
await asyncio.gather(waiter(event), setter(event))
asyncio.run(main())
9. asyncio.Semaphore
asyncio.Semaphore
is used to limit the number of coroutines accessing a resource concurrently.
Example
import asyncio
async def worker(semaphore, num):
async with semaphore:
print(f"Worker {num} is working")
await asyncio.sleep(2)
print(f"Worker {num} done")
async def main():
semaphore = asyncio.Semaphore(2) # Limit to 2 concurrent workers
await asyncio.gather(
worker(semaphore, 1),
worker(semaphore, 2),
worker(semaphore, 3)
)
asyncio.run(main())
10. asyncio.Timeout
asyncio.Timeout
allows you to specify a timeout for coroutines.
Example
import asyncio
async def long_task():
await asyncio.sleep(5)
async def main():
try:
await asyncio.wait_for(long_task(), timeout=2)
except asyncio.TimeoutError:
print("Task timed out")
asyncio.run(main())
Conclusion
The asyncio
module is a powerful tool for writing concurrent code in Python using asynchronous programming. It provides a range of components, including coroutines, tasks, and synchronization primitives, to manage and execute asynchronous operations. By understanding and leveraging these components, you can write efficient and scalable code for applications that involve I/O-bound tasks, networking, and other asynchronous activities.