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 classResultBase
; 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()
orset_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 toResultBase.exception()
will return this exception. The exception raised byResultBase.result()
will be aTaskFailedException
rather than the exception passed to this method, which matches the behaviour ofResultCapture
; see Exception handling.- Parameters:
exception – The exception to be stored.
- Raises:
FutureSetAgainException – If the result has already been set with
set_result()
orset_exception()
.
Future
makes use of the following exception class:
- exception aioresult.FutureSetAgainException¶
Bases:
Exception
Raised if
Future.set_result()
orFuture.set_exception()
called more than once.It can also be raised from a
ResultCapture
ifResultCapture.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
orFuture
that raised this exception.