Using futures

Motivation and usage

The Future class allows storing the result of an operation, either a return value or a raised exception. It differs from ResultCapture in that you manually specify the result by calling either Future.set_result() or Future.set_exception() rather than the result automatically being captured from some async function.

This is often useful when you are implementing an API in a library where requests can be sent to some remote server, but multiple requests can be outstanding at a time so the result is set in some separate async routine:

# Public function in the API: Send the request over some connection
def start_request(request_payload) -> aioresult.ResultBase:
    request_id = connection.send_request(request_payload)
    result = aioresult.Future()
    outstanding_requests[request_id] = result
    return result

# Hidden function in the API: In a separate task, wait for responses to any request
async def get_responses():
    while True:
        request_id, response = await connection.get_next_response()
        outstanding_requests[request_id].set_result(response)
        del outstanding_requests[request_id]

# Caller code: Use the API and returned Future object
async def make_request():
    f = start_request(my_request)
    await f.wait_done()
    print("result:", f.result())

If you need to wait for several futures to finish, in a similar way to asyncio.gather(), then you can use wait_all():

results = [start_request(i) for i in range(10)]
await aioresult.wait_all(results)
print("results:", *[f.result() for f in results])

Reference

class aioresult.Future

Bases: ResultBase

Stores a result or exception that is explicitly set by the caller.

Note

Future inherits most of its methods from its base class ResultBase; see the documentation for that class for the inherited methods.

set_result(result)

Sets the result of the future to the given value.

After calling this method, later calls to ResultBase.result() will return the value passed in.

Parameters:

result – The result value to be stored.

Raises:

FutureSetAgainException – If the result has already been set with set_result() or set_exception().

set_exception(exception: BaseException)

Sets the exception of the future to the given value.

After calling this method, later calls to ResultBase.result() will throw an exception and calls to ResultBase.exception() will return this exception. The exception raised by ResultBase.result() will be a TaskFailedException rather than the exception passed to this method, which matches the behaviour of ResultCapture; see Exception handling.

Parameters:

exception – The exception to be stored.

Raises:

FutureSetAgainException – If the result has already been set with set_result() or set_exception().

Future makes use of the following exception class:

exception aioresult.FutureSetAgainException

Bases: Exception

Raised if Future.set_result() or Future.set_exception() called more than once.

It can also be raised from a ResultCapture if ResultCapture.run() is called more than once.

It is raised with the future passed as the argument to the exception:

raise FutureSetAgainException(self)

This allows access to the future from the exception using the args attribute:

args: tuple[ResultBase]

1-tuple of the ResultCapture or Future that raised this exception.