Python asyncio.wait()

Summary: in this tutorial, you’ll learn about the asyncio.wait() function to run an iterable of awaitable objects concurrently.

Introduction to the Python asyncio wait() function

The asyncio.wait() function runs an iterable of awaitables objects and blocks until a specified condition.

Here’s the syntax of the asyncio.wait() function:

asyncio.wait(aws, *, timeout=None, return_when=ALL_COMPLETED)Code language: Python (python)

The asyncio.wait() function has the following parameters:

  • aws is iterable of awaitable objects that you want to run concurrently.
  • timeout (either int or float) specifies a maximum number of seconds to wait before returning the result.
  • return_when indicates when the function should return. The return_when accepts one of the constants in the table below.
ConstantDescription
FIRST_COMPLETEDReturn when all awaitables are complete or canceled.
FIRST_EXCEPTIONReturn when any awaitable is complete by raising an exception. If no awaitable raises an exception, the FIRST_EXCEPTION is equivalent to ALL_COMPLETED.
ALL_COMPLETEDReturn when all awaitables are complete or cancelled.

Note that these constants are in the asyncio library so you can reference them like asyncio.FIRST_COMPLETED

The asyncio.wait() returns two sets:

done, pending = await asyncio.wait(aws)Code language: Python (python)
  • done is a set of awaitables that are done.
  • pending is a set of awaitables that are pending.

Python asyncio wait() function examples

The following example illustrates how to use the asyncio.wait() function:

import asyncio
from asyncio import create_task


class APIError(Exception):
    pass


async def call_api(message, result=100, delay=3, raise_exception=False):
    print(message)
    await asyncio.sleep(delay)
    if raise_exception:
        raise APIError
    else:
        return result


async def main():
    task_1 = create_task(call_api('calling API 1...', result=1, delay=1))
    task_2 = create_task(call_api('calling API 2...', result=2, delay=2))
    task_3 = create_task(call_api('calling API 3...', result=3, delay=3))

    pending = (task_1, task_2, task_3)

    while pending:
        done, pending = await asyncio.wait(
            pending,
            return_when=asyncio.FIRST_COMPLETED
        )
        result = done.pop().result()
        print(result)


asyncio.run(main())Code language: Python (python)

How it works.

First, define the APIError class that extends the Exception class:

class APIError(Exception):
    passCode language: Python (python)

Second, define the call_api() function that simulates an asynchronous operation:

async def call_api(message, result=100, delay=3, raise_exception=False):
    print(message)
    await asyncio.sleep(delay)
    if raise_exception:
        raise APIError
    else:
        return resultCode language: Python (python)

Third, create three tasks that wrap the call_api() coroutines. Each coroutine returns a different number:

task_1 = create_task(call_api('calling API 1...', result=1, delay=1))
task_2 = create_task(call_api('calling API 2...', result=2, delay=2))
task_3 = create_task(call_api('calling API 3...', result=3, delay=3))

pending = (task_1, task_2, task_3)Code language: Python (python)

Finally, call the asyncio.wait() function to run the tasks inside a while loop. If all the tasks are complete, the pending will be empty, and the while loop will exit. In each iteration, we get the completed task from the done set and display the result:

while pending:
    done, pending = await asyncio.wait(
        pending,
        return_when=asyncio.FIRST_COMPLETED
    )
    result = done.pop().result()
    print(result)Code language: Python (python)

Summary

  • Use the asyncio.wait() to run tasks in an iterable concurrently.
Did you find this tutorial helpful ?