w3resource

Python Asyncio: A Comprehensive Guide to Asynchronous Programming

Introduction to Python Asynchronous Programming

Asyncio is a Python library used to write concurrent code using the async/await syntax. It's designed for managing asynchronous tasks and I/O-bound operations, allowing you to run multiple tasks in the same thread without blocking each other. This tutorial will guide you through using asyncio with practical examples, focusing on writing concise, readable, and efficient asynchronous code.

Example 1: Basic Async Function

This example demonstrates the basics of defining and running an asynchronous function using ‘asyncio’.

Code:

import asyncio
# Define an asynchronous function
async def greet():
    print("Hello,")
    await asyncio.sleep(1)  # Simulate an asynchronous operation
    print("world!")

# Run the asynchronous function
asyncio.run(greet()) 

Output:

Hello,
world!

Explanation:

  • 'async def greet()': Defines an asynchronous function using the 'async' keyword.
  • 'await asyncio.sleep(1)': Pauses the function for 1 second without blocking other operations.
  • 'asyncio.run(greet())': Runs the asynchronous function 'greet'. This function manages the event loop and executes the async function.

Example 2: Running Multiple Coroutines Concurrently

This example shows how to run multiple asynchronous functions concurrently using 'asyncio.gather'.

Code:

import asyncio

# Define an asynchronous function
async def say_hello():
    print("Hello!")
    await asyncio.sleep(1)
    print("Done saying hello.")

# Define another asynchronous function
async def say_goodbye():
    print("Goodbye!")
    await asyncio.sleep(2)
    print("Done saying goodbye.")

# Run multiple asynchronous functions concurrently
async def main():
    await asyncio.gather(say_hello(), say_goodbye())

asyncio.run(main())

Output:

Hello!
Goodbye!
Done saying hello.
Done saying goodbye.

Explanation:

  • async def say_hello() and async def say_goodbye(): Two asynchronous functions that print messages and sleep for different durations.
  • asyncio.gather(say_hello(), say_goodbye()): Runs both functions concurrently, allowing them to operate at the same time.
  • asyncio.run(main()): Executes the main function, which runs the two async functions together.

Example 3: Using Asyncio with an Asynchronous Queue

This example demonstrates using asyncio with an asynchronous queue to coordinate tasks.

Code:

import asyncio

# Define a coroutine that processes items from a queue
async def worker(queue):
    while not queue.empty():
        item = await queue.get()  # Get an item from the queue
        print(f'Processing {item}')
        await asyncio.sleep(1)  # Simulate processing time
        queue.task_done()  # Mark the task as done

# Main function to set up the queue and workers
async def main():
    queue = asyncio.Queue()

    # Put items into the queue
    for i in range(5):
        await queue.put(i)

    # Create a list of worker coroutines
    tasks = [asyncio.create_task(worker(queue)) for _ in range(3)]

    # Wait for all items in the queue to be processed
    await queue.join()

    # Cancel the worker tasks since the queue is empty
    for task in tasks:
        task.cancel()

# Run the main function
asyncio.run(main())

Output:

Processing 0
Processing 1
Processing 2
Processing 3
Processing 4

Explanation:

  • async def worker(queue): An asynchronous worker function that processes items from the queue.
  • await queue.get(): Retrieves an item from the queue asynchronously.
  • await queue.join(): Waits until all tasks in the queue have been processed.
  • task.cancel(): Cancels the remaining worker tasks once the queue is empty.
  • Concurrency with Async Queue: The workers process items concurrently without blocking each other, demonstrating the power of asyncio for task coordination.

Example 4: Handling Timeouts with Asyncio

This example illustrates how to handle timeouts for asynchronous tasks using 'asyncio.wait_for'.

Code:

import asyncio
# Define a long-running task
async def long_task():
    print("Starting a long task...")
    await asyncio.sleep(5)
    print("Long task completed.")

# Main function with timeout handling
async def main():
    try:
        # Run the long task with a timeout of 2 seconds
        await asyncio.wait_for(long_task(), timeout=2)
    except asyncio.TimeoutError:
        print("Task timed out!")

# Run the main function
asyncio.run(main())

Output:

Starting a long task...
Task timed out!

Explanation:

  • await asyncio.wait_for(long_task(), timeout=2): Attempts to run the long_task function with a 2-second timeout.
  • asyncio.TimeoutError: Raised if the task takes longer than the specified timeout, allowing you to handle the error gracefully.

Example 5: Creating and Using an Asyncio Event

This example shows how to use an asyncio event to synchronize tasks.

Code:

import asyncio
# Define a coroutine that waits for an event
async def waiter(event):
    print("Waiting for the event to be set...")
    await event.wait()  # Wait for the event to be set
    print("Event has been set, proceeding!")

# Define a coroutine that sets the event
async def setter(event):
    print("Setting the event in 3 seconds...")
    await asyncio.sleep(3)
    event.set()  # Set the event

# Main function to run the waiter and setter
async def main():
    event = asyncio.Event()

    # Create tasks for waiter and setter
    waiter_task = asyncio.create_task(waiter(event))
    setter_task = asyncio.create_task(setter(event))

    # Wait for both tasks to complete
    await asyncio.gather(waiter_task, setter_task)

# Run the main function
asyncio.run(main())

Output:

Waiting for the event to be set...
Setting the event in 3 seconds...
Event has been set, proceeding!

Explanation:

  • asyncio.Event(): Creates an event object used for synchronization between tasks.
  • await event.wait(): Makes the waiter task wait until the event is set.
  • event.set(): Sets the event, allowing the waiter task to continue.
  • Synchronization with Async Events: This pattern is useful for coordinating tasks that depend on each other.


Become a Patron!

Follow us on Facebook and Twitter for latest update.