Summary: in this tutorial, you’ll learn how to use the Python asyncio.gather()
function to run multiple asynchronous operations.
Introduction to the Python asyncio.gather() function #
Sometimes, you may want to run multiple asynchronous operations and get the results once they are complete. To do that you can use the asyncio.gather()
function:
gather(*aws, return_exceptions=False) -> Future[tuple[()]]
Code language: Python (python)
The asyncio.gather()
function has two parameters:
aws
is a sequence of awaitable objects. If any object in theaws
is a coroutine, theasyncio.gather()
function will automatically schedule it as a task.return_exceptions
isFalse
by default. If an exception occurs in an awaitable object, it is immediately propagated to the task that awaits onasyncio.gather()
. Other awaitables will continue to run and won’t be canceled.
The asyncio.gather()
returns the results of awaitables as a tuple with the same order as you pass the awaitables to the function.
If the return_exceptions
is True
. The asyncio.gather()
will add the exception if any to the result and not propagate the exception to the caller.
Python asyncio.gather() examples #
Let’s take some examples of using the asyncio.gather()
function.
1) Using asyncio.gather() to run multiple asynchronous operations #
The following example uses the asyncio.gather()
to run two asynchronous operations and displays the results:
import asyncio
async def call_api(message, result, delay=3):
print(message)
await asyncio.sleep(delay)
return result
async def main():
a, b = await asyncio.gather(
call_api('Calling API 1 ...', 1),
call_api('Calling API 2 ...', 2)
)
print(a, b)
asyncio.run(main())
Code language: Python (python)
Output:
Calling API 1 ...
Calling API 2 ...
100 200
Code language: Python (python)
How it works.
First, define a coroutine
that simulates an asynchronous operation. The call_api()
call_api()
displays a message, delays a number of seconds, and returns a result:
async def call_api(message, result, delay=3):
print(message)
await asyncio.sleep(delay)
return result
Code language: Python (python)
Second, use the asyncio.gather()
function to run two call_api()
:
async def main():
a, b = await asyncio.gather(
call_api('Calling API 1 ...', 100, 1),
call_api('Calling API 2 ...', 200, 2)
)
print(a, b)
Code language: Python (python)
The first coroutine takes 1 second and returns 100 while the second coroutine takes 2 seconds and returns 100.
After 2 seconds, the gather returns the result as a tuple that contains the result of the first and second coroutines.
Note that a is 100 and b is 200 which are the results of the corresponding coroutine that we pass to the asyncio.gather()
function.
2) Using asyncio.gather() to run multiple asynchronous operations with exceptions #
The following example shows how to use the asyncio.gather()
function to execute multiple asynchronous operations where an operation raises an exception:
import asyncio
class APIError(Exception):
def __init__(self, message):
self._message = message
def __str__(self):
return self._message
async def call_api_failed():
await asyncio.sleep(3)
raise APIError('API failed')
async def call_api(message, result, delay=3):
print(message)
await asyncio.sleep(delay)
return result
async def main():
a, b, c = await asyncio.gather(
call_api('Calling API 1 ...', 100, 1),
call_api('Calling API 2 ...', 200, 2),
call_api_failed()
)
print(a, b, c)
asyncio.run(main())
Code language: Python (python)
How it works.
First, define a new APIError
exception class that inherits from the Exception
class:
class APIError(Exception):
def __init__(self, message):
self._message = message
def __str__(self):
return self._message
Code language: Python (python)
Second, define the call_api_failed()
coroutine that delays 1 second and raises an APIError
exception:
async def call_api_failed():
await asyncio.sleep(3)
raise APIError('API failed')
Code language: Python (python)
Third, pass three coroutines to the asyncio.gather()
function. After one second, the call_api_failed()
raises an exception that immediately propagates to the asyncio.gather()
function:
async def main():
a, b, c = await asyncio.gather(
call_api('Calling API 1 ...', 100, 1),
call_api('Calling API 2 ...', 200, 2),
call_api_failed()
)
print(a, b, c)
Code language: Python (python)
If you run the program, you’ll see the APIError
exception.
3) Using asyncio.gather() to return an exception in the result #
To get the exception in the result, you set the return_exceptions
parameter to True
as follows:
import asyncio
class APIError(Exception):
def __init__(self, message):
self._message = message
def __str__(self):
return self._message
async def call_api(message, result, delay=3):
print(message)
await asyncio.sleep(delay)
return result
async def call_api_failed():
await asyncio.sleep(1)
raise APIError('API failed')
async def main():
a, b, c = await asyncio.gather(
call_api('Calling API 1 ...', 100, 1),
call_api('Calling API 2 ...', 200, 2),
call_api_failed(),
return_exceptions=True
)
print(a, b, c)
asyncio.run(main())
Code language: Python (python)
Output:
Calling API 1 ...
Calling API 2 ...
100 200 API failed
Code language: Python (python)
In this example, because the return_exceptions
is set to True
, the asyncio.gather()
returns the exception as part of the result.
Summary #
- The
asyncio.gather()
runs multiple asynchronous operations, wraps a coroutine as a task, and returns a tuple of results in the same order of awaitables. - Set
return_exceptions
toTrue
to allow errors to be returned as results.