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" 例外
   を送出します。

   重要:

     タスクが実行途中で消えないように、この関数の返り値への参照を保持
     してください。新しいタスクの作成に推奨される "create_task()" 関数
     も参照してください。 または、タスクへの参照を内部で保持する
     "asyncio.TaskGroup" を使ってください。

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

   バージョン 3.10 で非推奨: *obj* が Future に相当するオブジェクトで
   はなく、*loop* を指定せず、実行中のイベントループもない場合に、非推
   奨の警告が出ます。

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

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

   バージョン 3.10 で非推奨: *future* が Future に相当するオブジェクト
   ではなく、*loop* を指定せず、実行中のイベントループもない場合に、非
   推奨の警告が出ます。


Future オブジェクト
===================

class asyncio.Future(*, loop=None)

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

   Future は *awaitable* オブジェクトです。 コルーチンは Future を
   await して、結果か例外が設定されるか、キャンセルされるまで待機でき
   ます。 同じ Future を複数回 await でき、その結果は同じです。

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

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

   Future は、結果の型をパラメーターとする ジェネリック型 です。

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

   バージョン 3.10 で非推奨: *loop* を指定せず、実行中のイベントループ
   もない場合に、非推奨の警告が出ます。

   result()

      Future の結果を返します。

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

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

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

      Future の結果がまだ得られない場合は、"InvalidStateError" を送出
      します。

   set_result(result)

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

      Future がすでに *完了* している場合は、"InvalidStateError" を送
      出します。

   set_exception(exception)

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

      Future がすでに *完了* している場合は、"InvalidStateError" を送
      出します。

   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()" を使うことができます:

         # fut が完了したら print("Future:", fut) を呼び出す。
         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" を返します。

      省略可能な文字列引数 *msg* は、キャンセル済みの Future を await
      したときに送出する "CancelledError" の引数として渡されます。

      バージョン 3.9 で変更: *msg* パラメーターが追加されました。

   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):
       # delay 秒スリープする。
       await asyncio.sleep(delay)

       # Future fut の結果に value を設定する。
       fut.set_result(value)

   async def main():
       # 現在のイベントループを取得する。
       loop = asyncio.get_running_loop()

       # 新しい Future オブジェクトを作成する。
       fut = loop.create_future()

       # set_after() コルーチンを別のタスクで並行して実行する。
       # ここではイベントループへの参照をすでに持っているので、
       # 低水準の loop.create_task() API を使っている。
       # そうでなければ asyncio.create_task() を使えばよい。
       loop.create_task(
           set_after(fut, 1, '... world'))

       print('hello ...')

       # fut の結果が得られるまで待ち (1 秒)、表示する。
       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()" は省略可能な "msg" 引数を受け付けますが
    、"concurrent.futures.Future.cancel()" は受け付けません。
