asyncio.TaskGroup, Runner, and Timeout Backport

0.2.2 · active · verified Sat Apr 11

The `taskgroup` library provides a backport of the `asyncio.TaskGroup`, `asyncio.Runner`, and `asyncio.timeout` functionalities from Python 3.12.8 to older Python versions, specifically Python 3.8, 3.9, 3.10, and 3.11. This allows developers to leverage the structured concurrency model introduced in Python 3.11+ for `asyncio` in environments that are not yet able to upgrade to the latest Python releases.

Warnings

Install

Imports

Quickstart

This quickstart demonstrates the usage of `TaskGroup`, `Runner`, and `timeout` through the `taskgroup` backport (or `asyncio` directly if Python 3.11+). It shows how to create and manage multiple concurrent tasks with `TaskGroup`, how to run a top-level coroutine with `Runner`, and how to apply a timeout to an asynchronous operation.

import sys
import asyncio

# Conditionally import TaskGroup, run, and timeout based on Python version
if sys.version_info >= (3, 11):
    from asyncio import TaskGroup, run, timeout
else:
    from taskgroup import TaskGroup, run, timeout

async def task_printer(name, delay):
    print(f"Task {name}: Starting in {delay} seconds...")
    await asyncio.sleep(delay)
    print(f"Task {name}: Finished.")
    return f"Result from {name}"

async def main_task_group():
    print("Main: Creating tasks...")
    async with TaskGroup() as group:
        task1 = group.create_task(task_printer("A", 2))
        task2 = group.create_task(task_printer("B", 1))
        task3 = group.create_task(task_printer("C", 3))
    print("Main: All tasks in group finished.")
    print(f"Task A result: {task1.result()}")
    print(f"Task B result: {task2.result()}")
    print(f"Task C result: {task3.result()}")

async def main_runner():
    print("\n--- Using Runner ---")
    async def inner_coro():
        await task_printer("D", 0.5)
        await task_printer("E", 1.5)
    
    with Runner() as runner:
        runner.run(inner_coro())
    print("Runner finished.")

async def main_timeout():
    print("\n--- Using Timeout ---")
    async def long_running_task():
        await asyncio.sleep(5)
        print("Long running task completed (should not happen if timeout works).")
    
    try:
        async with timeout(2):
            await long_running_task()
    except TimeoutError:
        print("Task timed out as expected.")

if __name__ == "__main__":
    print(f"Running with {'asyncio' if sys.version_info >= (3, 11) else 'taskgroup backport'}.")
    run(main_task_group())
    run(main_runner())
    run(main_timeout())

view raw JSON →