# Future

ソースコード: Lib/asyncio/futures.py, Lib/asyncio/base_futures.py

Future オブジェクトは 低水準のコールバックベースのコード と高水準の async/await コードとの間を橋渡しします。

## Future の関数

asyncio.isfuture(obj)

  オブジェクト obj が下記のいずれかであれば `True` を返します:

  - `asyncio.Future` クラスのインスタンス

  - `asyncio.Task` クラスのインスタンス

  - `_asyncio_future_blocking` 属性を持った Future 的なオブジェクト

  Added in version 3.5.

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

  下記のいずれかを返します:

  - obj が `Future` オブジェクト、 `Task` オブジェクト、または Future 的なオブジェクト (`isfuture()` 関数を使って検査します) である場合には obj そのもの

  - 引数 obj がコルーチンである (`iscoroutine()` 関数を使って検査します) 場合には obj をラップした `Task` オブジェクト; この場合コルーチンは `ensure_future()` によりスケジュールされます。

  - 引数 obj が awaitable である (`inspect.isawaitable()` 関数を使って検査します) 場合には obj を await する `Task` オブジェクト

  引数 obj が上記のいずれにもあてはまらない場合は `TypeError` 例外を送出します。

  重要

  Save a reference to the result of this function, to avoid a task disappearing mid-execution.

  See also the `create_task()` function which is the preferred way for creating new tasks or use `asyncio.TaskGroup` which keeps reference to the task internally.

  バージョン 3.5.1 で変更: この関数はどんな awaitable なオブジェクトでも受け入れるようになりました。

  バージョン 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)

  `concurrent.futures.Future` オブジェクトを `asyncio.Future` オブジェクトでラップします。

  バージョン 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 オブジェクト

class asyncio.Future(*, loop=None)

  Future は非同期処理の最終結果を表すクラスです。スレッドセーフではありません。

  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. A Future can be awaited multiple times and the result is same.

  典型的には、 Future は低水準のコールバックベースのコード (たとえば asyncio の transports を使って実装されたプロトコル) が高水準の async/await と相互運用することを可能にするために利用されます。

  経験則は Future オブジェクトをユーザー向けの API であらわに利用しないことです。推奨される Future オブジェクトの生成方法は `loop.create_future()` を呼び出すことです。これによりイベントループの代替実装は、自身に最適化された Future オブジェクトの実装を合わせて提供することができます。

  バージョン 3.7 で変更: `contextvars` モジュールのサポートを追加。

  バージョン 3.10 で非推奨: Deprecation warning is emitted if loop is not specified and there is no running event loop.

  result()

    Future の結果を返します。

    Future が 完了 していて、 `set_result()` メソッドにより設定された結果を持っている場合は結果の値を返します。

    Future が 完了 していて、 `set_exception()` メソッドにより設定された例外を持っている場合はその例外を送出します。

    Future が キャンセルされた 場合、このメソッドは `CancelledError` 例外を送出します。

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

  set_result(result)

    Future を 完了 とマークし、結果を設定します。

    Raises an `InvalidStateError` error if the Future is already done.

  set_exception(exception)

    Future を 完了 とマークし、例外を設定します。

    Raises an `InvalidStateError` error if the Future is already done.

  done()

    Future が 完了 しているなら `True` を返します。

    Future は キャンセルされた か、または `set_result()` メソッドや `set_exception()` メソッドの呼び出しにより結果や例外が設定された場合に 完了 とみなされます。

  cancelled()

    Future が キャンセルされた 場合に `True` を返します。

    通常の場合、このメソッドは Future に処理結果や例外を設定する前に Future が キャンセルされていない ことを確認するために使用されます:

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

  add_done_callback(callback, *, context=None)

    Future が 完了 したときに実行されるコールバックを追加します。

    callback は Future オブジェクトだけを引数にとって呼び出されます。

    このメソッドが呼び出される時点ですでに Future が 完了 している場合、コールバックは `loop.call_soon()` メソッドによりスケジュールされます。

    オプションのキーワード引数 context を使って、コールバック*callback* を実行する際のコンテキスト `contextvars.Context` を設定することができます。コンテキスト context が指定されない場合は現在のコンテキストが使われます。

    コールバックにパラメータを渡すには、次の例のように `functools.partial()` を使うことができます:

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

    バージョン 3.7 で変更: キーワード引数 context が追加されました。詳細は PEP 567 を参照してください。

  remove_done_callback(callback)

    コールバックリストから callback を削除します。

    削除されたコールバックの数を返します。コールバックが複数回追加されていない限り、通常は1が返ります。

  cancel(msg=None)

    Future をキャンセルし、コールバックをスケジュールします。

    Future がすでに 完了 または キャンセル された場合、 `False` を返します。そうでない場合 Future の状態を キャンセル に変更した上でコールバックをスケジュールし、 `True` を返します。

    バージョン 3.9 で変更: Added the msg parameter.

  exception()

    この Future オブジェクトに設定された例外を返します。

    例外 (または例外が設定されていないときは `None`) は Future が 完了 している場合のみ返されます。

    Future が キャンセルされた 場合、このメソッドは `CancelledError` 例外を送出します。

    Future が 未完了 の場合、このメソッドは `InvalidStateError` 例外を送出します。

  get_loop()

    Future オブジェクトが束縛されているイベントループを返します。

    Added in version 3.7.

この例は Future オブジェクトを生成し、Future に結果を設定するための非同期タスクを生成してスケジュールし、そして Future に結果が設定されるまで待機します:

    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())

重要

Future オブジェクトは `concurrent.futures.Future` を模倣してデザインされました。両者の重要な違いは以下の通りです:

- asyncio の Futures と異なり、 `concurrent.futures.Future` インスタンスは待ち受けできません。

- `asyncio.Future.result()` と `asyncio.Future.exception()` は timeout 引数を取りません。

- `asyncio.Future.result()` と `asyncio.Future.exception()` は Future が 未完了 の場合に `InvalidStateError` 例外を送出します。

- `asyncio.Future.add_done_callback()` メソッドによって登録されたコールバックは、即座に呼び出されません。代わりにコールバックは `loop.call_soon()` によりスケジュールされます。

- asyncio の Future は `concurrent.futures.wait()` および `concurrent.futures.as_completed()` との互換性がありません。

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