Futures
*******

**Source code:** Lib/asyncio/futures.py, Lib/asyncio/base_futures.py

======================================================================

*Future* objects are used to bridge **low-level callback-based code**
with high-level async/await code.


Future Functions
================

asyncio.isfuture(obj)

   Return "True" if *obj* is either of:

   * an instance of "asyncio.Future",

   * an instance of "asyncio.Task",

   * a Future-like object with a "_asyncio_future_blocking" attribute.

   New in version 3.5.

asyncio.ensure_future(obj, *, loop=None)

   Return:

   * *obj* argument as is, if *obj* is a "Future", a "Task", or a
     Future-like object ("isfuture()" is used for the test.)

   * a "Task" object wrapping *obj*, if *obj* is a coroutine
     ("iscoroutine()" is used for the test); in this case the
     coroutine will be scheduled by "ensure_future()".

   * a "Task" object that would await on *obj*, if *obj* is an
     awaitable ("inspect.isawaitable()" is used for the test.)

   If *obj* is neither of the above a "TypeError" is raised.

   Important:

     See also the "create_task()" function which is the preferred way
     for creating new Tasks.Save a reference to the result of this
     function, to avoid a task disappearing mid execution.

   Changed in version 3.5.1: The function accepts any *awaitable*
   object.

   Deprecated since version 3.10: Deprecation warning is emitted if
   *obj* is not a Future-like object and *loop* is not specified and
   there is no running event loop.

asyncio.wrap_future(future, *, loop=None)

   Wrap a "concurrent.futures.Future" object in a "asyncio.Future"
   object.

   Deprecated since version 3.10: Deprecation warning is emitted if
   *future* is not a Future-like object and *loop* is not specified
   and there is no running event loop.


Future Object
=============

class asyncio.Future(*, loop=None)

   A Future represents an eventual result of an asynchronous
   operation.  Not thread-safe.

   Future is an *awaitable* object.  Coroutines can await on Future
   objects until they either have a result or an exception set, or
   until they are cancelled.

   Typically Futures are used to enable low-level callback-based code
   (e.g. in protocols implemented using asyncio transports) to
   interoperate with high-level async/await code.

   The rule of thumb is to never expose Future objects in user-facing
   APIs, and the recommended way to create a Future object is to call
   "loop.create_future()".  This way alternative event loop
   implementations can inject their own optimized implementations of a
   Future object.

   Changed in version 3.7: Added support for the "contextvars" module.

   Deprecated since version 3.10: Deprecation warning is emitted if
   *loop* is not specified and there is no running event loop.

   result()

      Return the result of the Future.

      If the Future is *done* and has a result set by the
      "set_result()" method, the result value is returned.

      If the Future is *done* and has an exception set by the
      "set_exception()" method, this method raises the exception.

      If the Future has been *cancelled*, this method raises a
      "CancelledError" exception.

      If the Future's result isn't yet available, this method raises a
      "InvalidStateError" exception.

   set_result(result)

      Mark the Future as *done* and set its result.

      Raises a "InvalidStateError" error if the Future is already
      *done*.

   set_exception(exception)

      Mark the Future as *done* and set an exception.

      Raises a "InvalidStateError" error if the Future is already
      *done*.

   done()

      Return "True" if the Future is *done*.

      A Future is *done* if it was *cancelled* or if it has a result
      or an exception set with "set_result()" or "set_exception()"
      calls.

   cancelled()

      Return "True" if the Future was *cancelled*.

      The method is usually used to check if a Future is not
      *cancelled* before setting a result or an exception for it:

         if not fut.cancelled():
             fut.set_result(42)

   add_done_callback(callback, *, context=None)

      Add a callback to be run when the Future is *done*.

      The *callback* is called with the Future object as its only
      argument.

      If the Future is already *done* when this method is called, the
      callback is scheduled with "loop.call_soon()".

      An optional keyword-only *context* argument allows specifying a
      custom "contextvars.Context" for the *callback* to run in. The
      current context is used when no *context* is provided.

      "functools.partial()" can be used to pass parameters to the
      callback, e.g.:

         # Call 'print("Future:", fut)' when "fut" is done.
         fut.add_done_callback(
             functools.partial(print, "Future:"))

      Changed in version 3.7: The *context* keyword-only parameter was
      added. See **PEP 567** for more details.

   remove_done_callback(callback)

      Remove *callback* from the callbacks list.

      Returns the number of callbacks removed, which is typically 1,
      unless a callback was added more than once.

   cancel(msg=None)

      Cancel the Future and schedule callbacks.

      If the Future is already *done* or *cancelled*, return "False".
      Otherwise, change the Future's state to *cancelled*, schedule
      the callbacks, and return "True".

      Changed in version 3.9: Added the *msg* parameter.

      Deprecated since version 3.11, will be removed in version 3.14:
      *msg* parameter is ambiguous when multiple "cancel()" are called
      with different cancellation messages. The argument will be
      removed.

   exception()

      Return the exception that was set on this Future.

      The exception (or "None" if no exception was set) is returned
      only if the Future is *done*.

      If the Future has been *cancelled*, this method raises a
      "CancelledError" exception.

      If the Future isn't *done* yet, this method raises an
      "InvalidStateError" exception.

   get_loop()

      Return the event loop the Future object is bound to.

      New in version 3.7.

This example creates a Future object, creates and schedules an
asynchronous Task to set result for the Future, and waits until the
Future has a result:

   async def set_after(fut, delay, value):
       # Sleep for *delay* seconds.
       await asyncio.sleep(delay)

       # Set *value* as a result of *fut* Future.
       fut.set_result(value)

   async def main():
       # Get the current event loop.
       loop = asyncio.get_running_loop()

       # Create a new Future object.
       fut = loop.create_future()

       # Run "set_after()" coroutine in a parallel Task.
       # We are using the low-level "loop.create_task()" API here because
       # we already have a reference to the event loop at hand.
       # Otherwise we could have just used "asyncio.create_task()".
       loop.create_task(
           set_after(fut, 1, '... world'))

       print('hello ...')

       # Wait until *fut* has a result (1 second) and print it.
       print(await fut)

   asyncio.run(main())

Important:

  The Future object was designed to mimic "concurrent.futures.Future".
  Key differences include:

  * unlike asyncio Futures, "concurrent.futures.Future" instances
    cannot be awaited.

  * "asyncio.Future.result()" and "asyncio.Future.exception()" do not
    accept the *timeout* argument.

  * "asyncio.Future.result()" and "asyncio.Future.exception()" raise
    an "InvalidStateError" exception when the Future is not *done*.

  * Callbacks registered with "asyncio.Future.add_done_callback()" are
    not called immediately.  They are scheduled with
    "loop.call_soon()" instead.

  * asyncio Future is not compatible with the
    "concurrent.futures.wait()" and
    "concurrent.futures.as_completed()" functions.

  * "asyncio.Future.cancel()" accepts an optional "msg" argument, but
    "concurrent.futures.cancel()" does not.

    Deprecated since version 3.11, will be removed in version 3.14:
    *msg* parameter is ambiguous when multiple "cancel()" are called
    with different cancellation messages. The argument will be
    removed.
