Python asyncio – Task Wrapping Examples (basic to advanced)

Updated: February 12, 2024 By: Guest Contributor Post a comment

Introduction

As asynchronous programming in Python evolves, asyncio remains at the forefront, transforming mundane I/O operations into non-blocking tasks. This guide delves into task wrapping, essential for optimizing asynchronous code throughput.

Basics of asyncio Task

Before diving into advanced usage, understanding the fundamentals of the asyncio task is crucial. At its core, asyncio.Task converts coroutines into tasks, enabling them to run concurrently. Here’s a simple example:

import asyncio

async def main():
    print('Hello')
    await asyncio.sleep(1)
    print('world')

asyncio.run(main())

This demonstrates a basic asyncio coroutine, paused with await asyncio.sleep(1), highlighting asynchronous execution.

Running Concurrent Tasks

Next, we explore running tasks concurrently, a stepping stone to more sophisticated applications:

import asyncio

async def coroutine1():
    await asyncio.sleep(1)
    return 'coroutine1 complete'

async def coroutine2():
    await asyncio.sleep(2)
    return 'coroutine2 complete'

async def main():
    task1 = asyncio.create_task(coroutine1())
    task2 = asyncio.create_task(coroutine2())

    print(await task1)
    print(await task2)

asyncio.run(main())

Here, coroutine1 and coroutine2 run concurrently, demonstrating the efficiency of task wrapping in handling multiple operations simultaneously.

Advanced Task Management

Advancing further, we’ll explore using a queue for managing a pool of tasks dynamically. This approach is particularly effective for scenarios involving numerous tasks of varying complexity:

import asyncio
from asyncio import Queue

async def worker(name, queue):
    while True:
        sleep_time = await queue.get()
        await asyncio.sleep(sleep_time)
        queue.task_done()
        print(f'Worker {name} completed task')

async def main():
    queue = Queue(maxsize=5)
    workers = [asyncio.create_task(worker(f'Worker {i}', queue)) for i in range(3)]

    for sleep_time in [2, 1, 3, 2, 1]:
        await queue.put(sleep_time)

    await queue.join()

    for worker in workers:
        worker.cancel()

asyncio.run(main())

This example deploys a worker pool consuming tasks from a queue, an advanced technique that showcases the power of asyncio in real-world applications.

Conclusion

Throughout this guide, we’ve explored the essential concepts of asyncio task wrapping, from the fundamentals to more advanced applications. The versatility and efficiency of asyncio tasks are indispensable for modern asynchronous programming, offering a pathway to high-performance applications.