Sling Academy
Home/Python/Python asyncio.gather() function (with examples)

Python asyncio.gather() function (with examples)

Last updated: July 26, 2023

Overview

In Python, asyncio.gather() is a function that allows you to run multiple coroutines or awaitable objects concurrently and get the results once they are complete. It was added to Python in version 3.4, as part of the asyncio module.

asyncio.gather() is used for writing concurrent code with the async/await syntax, which is often a good fit for IO-bound and high-level structured network code. For example, you can use the asyncio.gather() function to call multiple APIs in parallel and process the responses.

Syntax:

asyncio.gather(*aws, return_exceptions=False, loop=None)

Where:

  • *aws: a sequence of coroutines or awaitable objects to be executed concurrently. The * operator unpacks the sequence into individual arguments, allowing them to be passed to the function as separate arguments.
  • return_exceptions: a boolean value that controls how exceptions are handled. If False (the default), an exception raised by any awaitable object will be immediately propagated to the task that awaits on asyncio.gather(). Other awaitable objects will continue to run and won’t be canceled. If True, exceptions will be captured and returned in the result list along with successful results.
  • loop: (deprecated since Python 3.8) the event loop to use for executing the awaitable objects. If not specified, the current event loop will be used.

The returned value of the asyncio.gather() function is a Future object that represents the aggregation of the results of the awaitable objects. When all awaitable objects are done, the Future object’s result is a list of results with the same order as the input sequence. You can use the await expression to get the result of the Future object.

For more clarity, see the practical examples below.

Examples

Basic example

This one shows how to use the asyncio.gather() function to run two coroutines that print some messages and sleep for a random amount of time:

import asyncio
import random

async def say_hello(name):
    print(f"Hello, {name}!")
    await asyncio.sleep(random.randint(1, 3))
    print(f"Goodbye, {name}!")
    return f"{name} is done"

async def main():
    # run two coroutines concurrently and get the results
    result = await asyncio.gather(
        say_hello("Mr. Turtle"),
        say_hello("Mr. Wolf")
    )
    # print the results
    print(result)

# run the main coroutine
asyncio.run(main())

Output:

Hello, Mr. Turtle!
Hello, Mr. Wolf!
Goodbye, Mr. Turtle!
Goodbye, Mr. Wolf!
['Mr. Turtle is done', 'Mr. Wolf is done']

Advanced example

In this example, we’ll use the asyncio.gather() function with the return_exceptions parameter to handle exceptions raised by the awaitable objects. The return_exceptions parameter can be True or False (the default). If True, exceptions will be captured and returned in the result list along with successful results. If False, an exception raised by any awaitable object will be immediately propagated to the task that awaits on asyncio.gather(). Other awaitable objects will continue to run and won’t be canceled.

import asyncio


async def divide(x, y):
    print(f"Dividing {x} by {y}")
    await asyncio.sleep(1)
    if y == 0:
        raise ZeroDivisionError("Cannot divide by zero")
    return x / y


async def main():
    # run three coroutines concurrently and get the results
    # one of them will raise an exception
    result = await asyncio.gather(
        divide(10, 2),
        divide(20, 0),
        divide(30, 5),
        return_exceptions=True,  # capture exceptions
    )
    # print the results or handle the exceptions
    for r in result:
        if isinstance(r, Exception):
            print(f"Error: {r}")
        else:
            print(f"Result: {r}")


# run the main coroutine
asyncio.run(main())

Output:

Dividing 10 by 2
Dividing 20 by 0
Dividing 30 by 5
Result: 5.0
Error: Cannot divide by zero
Result: 6.0

Conclusion

You’ve learned the fundamentals of the asyncio.gather() function and walked through a couple of code examples of using it in practice. At this point, you should be able to use it in your production projects with confidence. This tutorial ends here. Happy coding & enjoy programming with async/await in modern Python.

Next Article: Python: Using the result returned by an async function (4 examples)

Previous Article: Python: Using async/await with loops (for & while loops)

Series: Python Asynchronous Programming Tutorials

Python

You May Also Like

  • Python TypeError: write() argument must be str, not bytes
  • 4 ways to install Python modules on Windows without admin rights
  • Python TypeError: object of type ‘NoneType’ has no len()
  • Python: How to access command-line arguments (3 approaches)
  • Understanding ‘Never’ type in Python 3.11+ (5 examples)
  • Python: 3 Ways to Retrieve City/Country from IP Address
  • Using Type Aliases in Python: A Practical Guide (with Examples)
  • Python: Defining distinct types using NewType class
  • Using Optional Type in Python (explained with examples)
  • Python: How to Override Methods in Classes
  • Python: Define Generic Types for Lists of Nested Dictionaries
  • Python: Defining type for a list that can contain both numbers and strings
  • Using TypeGuard in Python (Python 3.10+)
  • Python: Using ‘NoReturn’ type with functions
  • Type Casting in Python: The Ultimate Guide (with Examples)
  • Python: Using type hints with class methods and properties
  • Python: Typing a function with default parameters
  • Python: Typing a function that can return multiple types
  • Python: Typing a function with *args and **kwargs