Futures

A Future is an object that is used to store a value that is not available when the future is created, but that will be available at a later time. This is an alternative to callbacks in the typical use case of executing an asynchronous action. An asynchronous function is called, so its return value is not available yet. One way to deal with this is to provide a callback that will be called when the action completes. Another option is to return a future in the asynchronous function and set the result of the action in future once the action has completed. The caller of the asynchronous function can then be notified when future is set.

The following figure shows how a Future object can be used:

Figure 2.6: Using a Future object to wait for asynchronous action results

Let's look at an example. The following program simulates an asynchronous action whose result is 42. This result value is put into future, and the value of the future is printed on the console:

import asyncio
f = asyncio.Future()
print("Future is done: {}".format(f.done()))
f.set_result(42) # this is done asynchronously in a real code
print("Future is done: {}".format(f.done()))
print("result is: {}".format(f.result())

Running this code prints the following output:

Future is done: False
Future is done: True
result is: 42

Let's see what happens here. First, the asyncio module is imported. Then a Future object is created and stored in the f variable. At that point, the Future object does not contain any value yet. This can be checked with the done method. The done method indicates whether future has completed or not. A future is completed if it has been set to a value or if it has been cancelled. The print statement confirms that the future is not completed yet. After that, the future value is set to 42 with the set_result method. The set_result method marks future as completed and sets its value. From that point, the future is completed, which is confirmed by the second print statement. The value of the future is then retrieved with the call to the result method.

The result method returns the value of future, but only if has been set previously with a call to set_result. If the future has no value set or if it has been canceled, then the result method raises an exception.

For example, look at the following code:

f = asyncio.Future()
print("result is: {}".format(f.result()))

It raises an InvalidStateError because future is not completed yet:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
asyncio.base_futures.InvalidStateError: Result is not set.

Look at the following code:

f = asyncio.Future()
f.cancel()
print("result is: {}".format(f.result()))

It raises a CancelledError exception because the future has been canceled:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
concurrent.futures._base.CancelledError

Canceling a future is done with the cancel method. There is no value associated with cancelation. Canceling a future is useful when an action has been started, but it must be interrupted before it completes. In this case, a future has no value, but any client waiting for it can be notified that it has been canceled.

It is also possible to put an exception into future with the set_exception method. If future contains an exception, the result method raises this exception when being called. The exception can also be retrieved with the exception getter method.

The last feature of future is the ability to attach callbacks for completion. The add_done_callback method associates a completion callback with future. This callback is called when future completes. The remove_done_callback method removes a callback previously associated with future. However, this feature is rarely needed when writing applicative code in AsyncIO.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.83.199