コルーチンと Task
*****************

この節では、コルーチンと Task を利用する高レベルの asyncio の API の概
略を解説します。

* コルーチン

* Awaitable

* 非同期プログラムの実行

* Task の作成

* スリープ

* 並行な Task 実行

* キャンセルからの保護

* タイムアウト

* 要素の終了待機

* スレッド内での実行

* 外部スレッドからのスケジュール

* イントロスペクション

* Task オブジェクト

* ジェネレータベースのコルーチン


コルーチン
==========

**Source code:** Lib/asyncio/coroutines.py

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

async/await 構文で宣言された *コルーチン* は、 asyncio を使ったアプリ
ケーションを書くのに推奨される方法です。例えば、次のコードスニペットは
"hello" を出力し、そこから 1 秒待って "world" を出力します:

   >>> import asyncio

   >>> async def main():
   ...     print('hello')
   ...     await asyncio.sleep(1)
   ...     print('world')

   >>> asyncio.run(main())
   hello
   world

単にコルーチンを呼び出しただけでは、コルーチンの実行スケジュールは予約
されていないことに注意してください:

   >>> main()
   <coroutine object main at 0x1053bb7c8>

実際にコルーチンを走らせるために、 asyncio は3つの機構を提供しています
:

* 最上位のエントリーポイントである "main()" 関数を実行する
  "asyncio.run()" 関数 (上の例を参照してください。)

* コルーチンを await すること。次のコード片は 1 秒間待機した後に
  "hello" と出力し、 *更に* 2 秒間待機してから "world" と出力します:

     import asyncio
     import time

     async def say_after(delay, what):
         await asyncio.sleep(delay)
         print(what)

     async def main():
         print(f"started at {time.strftime('%X')}")

         await say_after(1, 'hello')
         await say_after(2, 'world')

         print(f"finished at {time.strftime('%X')}")

     asyncio.run(main())

  予想される出力:

     started at 17:13:52
     hello
     world
     finished at 17:13:55

* asyncio の "Tasks" としてコルーチンを並行して走らせる
  "asyncio.create_task()" 関数。

  上のコード例を編集して、ふたつの "say_after" コルーチンを *並行して*
  走らせてみましょう:

     async def main():
         task1 = asyncio.create_task(
             say_after(1, 'hello'))

         task2 = asyncio.create_task(
             say_after(2, 'world'))

         print(f"started at {time.strftime('%X')}")

         # Wait until both tasks are completed (should take
         # around 2 seconds.)
         await task1
         await task2

         print(f"finished at {time.strftime('%X')}")

  予想される出力が、スニペットの実行が前回よりも 1 秒早いことを示して
  いることに注意してください:

     started at 17:14:32
     hello
     world
     finished at 17:14:34


Awaitable
=========

あるオブジェクトを "await" 式の中で使うことができる場合、そのオブジェ
クトを **awaitable** オブジェクトと言います。多くの asyncio API は
awaitable を受け取るように設計されています。

*awaitable* オブジェクトには主に3つの種類があります: **コルーチン**,
**Task**, そして **Future** です

-[ コルーチン ]-

Python のコルーチンは *awaitable* であり、他のコルーチンから待機される
ことができます:

   import asyncio

   async def nested():
       return 42

   async def main():
       # Nothing happens if we just call "nested()".
       # A coroutine object is created but not awaited,
       # so it *won't run at all*.
       nested()

       # Let's do it differently now and await it:
       print(await nested())  # will print "42".

   asyncio.run(main())

重要:

  このドキュメントにおいて「コルーチン」という用語は以下2つの密接に関
  連した概念に対して使用できます:

  * *コルーチン関数*: "async def" 関数;

  * *コルーチンオブジェクト*: *コルーチン関数* を呼び出すと返ってくる
    オブジェクト.

asyncio は、古くからある ジェネレータベース のコルーチンもサポートして
います。

-[ Task ]-

*Task* は、コルーチンを *並行に* スケジュールするのに使います。

"asyncio.create_task()" のような関数で、コルーチンが *Task* にラップさ
れているとき、自動的にコルーチンは即時実行されるようにスケジュールされ
ます:

   import asyncio

   async def nested():
       return 42

   async def main():
       # Schedule nested() to run soon concurrently
       # with "main()".
       task = asyncio.create_task(nested())

       # "task" can now be used to cancel "nested()", or
       # can simply be awaited to wait until it is complete:
       await task

   asyncio.run(main())

-[ Future ]-

"Future" は、非同期処理の **最終結果** を表現する特別な **低レベルの**
awaitable オブジェクトです。

Future オブジェクトが *待機 (await) されている* とは、Future がどこか
他の場所で解決されるまでコルーチンが待機するということです。

asyncioのFutureオブジェクトを使うと、async/awaitとコールバック形式のコ
ードを併用できます。

通常、アプリケーション水準のコードで Future オブジェクトを作る **必要
はありません** 。

Future オブジェクトはライブラリや asyncio のAPIで外部に提供されること
もあり、await （待機）されることができます:

   async def main():
       await function_that_returns_a_future_object()

       # this is also valid:
       await asyncio.gather(
           function_that_returns_a_future_object(),
           some_python_coroutine()
       )

Future オブジェクトを返す低レベル関数の良い例は
"loop.run_in_executor()" です。


非同期プログラムの実行
======================

asyncio.run(coro, *, debug=False)

   *coroutine* *coro* を実行し、結果を返します。

   この関数は、非同期イベントループの管理と *非同期ジェネレータの終了
   処理* およびスレッドプールのクローズ処理を行いながら、渡されたコル
   ーチンを実行します。

   この関数は、同じスレッドで他の非同期イベントループが実行中のときは
   呼び出せません。

   *debug* が "True" の場合、イベントループはデバッグモードで実行され
   ます。

   この関数は常に新しいイベントループを作成し、終了したらそのイベント
   ループを閉じます。 この関数は非同期プログラムのメインのエントリーポ
   イントとして使われるべきで、理想的には 1 回だけ呼び出されるべきです
   。

   以下はプログラム例です:

      async def main():
          await asyncio.sleep(1)
          print('hello')

      asyncio.run(main())

   バージョン 3.7 で追加.

   バージョン 3.9 で変更: "loop.shutdown_default_executor()" メソッド
   を使うように更新されました。

   注釈:

     "asyncio.run()" のソースコードは Lib/asyncio/runners.py にありま
     す。


Task の作成
===========

**ソースコード:** Lib/asyncio/tasks.py

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

asyncio.create_task(coro, *, name=None)

   *coro* coroutine を "Task" でラップし、その実行をスケジュールします
   。 Task オブジェクトを返します。

   もし *name* が "None" でない場合、"Task.set_name()" を使用し、
   *name* がタスクの名前として設定されます。

   その Task オブジェクトは "get_running_loop()" から返されたループの
   中で実行されます。現在のスレッドに実行中のループが無い場合は、
   "RuntimeError" が送出されます。

   重要:

     タスクが実行中に消えないように、この関数の結果の参照を保存してく
     ださい。イベントループは弱い参照のみを保持します。ほかに参照元の
     ないタスクは、完了していなくてもガーベジコレクションされる可能性
     があります。信頼性のある "fire-and-forget" バックグラウンドタスク
     が必要な場合、コレクションを使ってください。

        background_tasks = set()

        for i in range(10):
            task = asyncio.create_task(some_coro(param=i))

            # Add task to the set. This creates a strong reference.
            background_tasks.add(task)

            # To prevent keeping references to finished tasks forever,
            # make each task remove its own reference from the set after
            # completion:
            task.add_done_callback(background_tasks.discard)

   バージョン 3.7 で追加.

   バージョン 3.8 で変更: *name* パラメータを追加しました。


スリープ
========

coroutine asyncio.sleep(delay, result=None)

   *delay* 秒だけ停止します。

   *result* が提供されている場合は、コルーチン完了時にそれが呼び出し元
   に返されます。

   "sleep()" は常に現在の Task を一時中断し、他の Task が実行されるの
   を許可します。

   delay を 0 に設定することで、他のタスクを実行可能にする最適な方針を
   提供します。この方法は、実行時間の長い関数が、その実行時間全体にわ
   たってイベントループをブロックしないようにするために利用できます。

   バージョン 3.8 で非推奨、バージョン 3.10 で削除: The "loop"
   parameter.  This function has been implicitly getting the current
   running loop since 3.7.  See What's New in 3.10's Removed section
   for more information.

   現在の時刻を5秒間、毎秒表示するコルーチンの例:

      import asyncio
      import datetime

      async def display_date():
          loop = asyncio.get_running_loop()
          end_time = loop.time() + 5.0
          while True:
              print(datetime.datetime.now())
              if (loop.time() + 1.0) >= end_time:
                  break
              await asyncio.sleep(1)

      asyncio.run(display_date())

   バージョン 3.10 で変更: *loop* パラメータが削除されました。


並行な Task 実行
================

awaitable asyncio.gather(*aws, return_exceptions=False)

   *aws* シーケンスにある awaitable オブジェクト を *並行* 実行します
   。

   *aws* にある awaitable がコルーチンである場合、自動的に Task として
   スケジュールされます。

   全ての awaitable が正常終了した場合、その結果は返り値を集めたリスト
   になります。 返り値の順序は、 *aws* での awaitable の順序に相当しま
   す。

   *return_exceptions* が "False" である場合(デフォルト)、"gather()"
   で await しているタスクに対して、最初の例外が直接伝えられます。
   *aws* に並んでいる他の awaitable は、**キャンセルされずに** 引き続
   いて実行されます。

   *return_exceptions* が "True" だった場合、例外は成功した結果と同じ
   ように取り扱われ、結果リストに集められます。

   "gather()" が *キャンセル* された場合、起動された全ての (未完了の)
   awaitable も *キャンセル* されます。

   *aws* シーケンスにある Task あるいは Future が *キャンセル* された
   場合、 "CancelledError" を送出したかのうように扱われます。つまり、
   この場合 "gather()" 呼び出しはキャンセル *されません*。 これは、起
   動された 1 つの Task あるいは Future のキャンセルが、他の Task ある
   いは Future のキャンセルを引き起こすのを避けるためです。

   バージョン 3.10 で変更: *loop* パラメータが削除されました。

   以下はプログラム例です:

      import asyncio

      async def factorial(name, number):
          f = 1
          for i in range(2, number + 1):
              print(f"Task {name}: Compute factorial({number}), currently i={i}...")
              await asyncio.sleep(1)
              f *= i
          print(f"Task {name}: factorial({number}) = {f}")
          return f

      async def main():
          # Schedule three calls *concurrently*:
          L = await asyncio.gather(
              factorial("A", 2),
              factorial("B", 3),
              factorial("C", 4),
          )
          print(L)

      asyncio.run(main())

      # Expected output:
      #
      #     Task A: Compute factorial(2), currently i=2...
      #     Task B: Compute factorial(3), currently i=2...
      #     Task C: Compute factorial(4), currently i=2...
      #     Task A: factorial(2) = 2
      #     Task B: Compute factorial(3), currently i=3...
      #     Task C: Compute factorial(4), currently i=3...
      #     Task B: factorial(3) = 6
      #     Task C: Compute factorial(4), currently i=4...
      #     Task C: factorial(4) = 24
      #     [2, 6, 24]

   注釈:

     *return_exceptions* が False の場合、いったん完了状態となった
     gather() をキャンセルしても起動された awaitables がキャンセルされ
     ないことがあります。例えば、 gather は例外を呼び出し元に送出した
     あと完了状態になることがあるため、 (起動した awaitable のいずれか
     から送出された) gather からの例外をキャッチした後で
     "gather.cancel()" を呼び出しても、他の awaitable がキャンセルされ
     ない可能性があります。

   バージョン 3.7 で変更: *gather* 自身がキャンセルされた場合は、
   *return_exceptions* の値に関わらずキャンセルが伝搬されます。

   バージョン 3.10 で変更: *loop* パラメータが削除されました。

   バージョン 3.10 で非推奨: Deprecation warning is emitted if no
   positional arguments are provided or not all positional arguments
   are Future-like objects and there is no running event loop.


キャンセルからの保護
====================

awaitable asyncio.shield(aw)

   "キャンセル" から awaitable オブジェクト を保護します。

   *aw* がコルーチンだった場合、自動的に Task としてスケジュールされま
   す。

   文:

      task = asyncio.create_task(something())
      res = await shield(task)

   は、以下と同じです

      res = await something()

   それを含むコルーチンがキャンセルされた場合を *除き*、"something()"
   内で動作している Task はキャンセルされません。 "something()" 側から
   見るとキャンセルは発生しません。 呼び出し元がキャンセルされた場合で
   も、 "await" 式は "CancelledError" を送出します。

   注意: "something()" が他の理由 (例えば、原因が自分自身) でキャンセ
   ルされた場合は "shield()" でも保護できません。

   完全にキャンセルを無視したい場合 (推奨はしません) は、 "shield()"
   関数は次のように try/except 節と組み合わせることになるでしょう:

      task = asyncio.create_task(something())
      try:
          res = await shield(task)
      except CancelledError:
          res = None

   重要:

     Save a reference to tasks passed to this function, to avoid a
     task disappearing mid-execution. The event loop only keeps weak
     references to tasks. A task that isn't referenced elsewhere may
     get garbage collected at any time, even before it's done.

   バージョン 3.10 で変更: *loop* パラメータが削除されました。

   バージョン 3.10 で非推奨: Deprecation warning is emitted if *aw* is
   not Future-like object and there is no running event loop.


タイムアウト
============

coroutine asyncio.wait_for(aw, timeout)

   *aw* awaitable が、完了するかタイムアウトになるのを待ちます。

   *aw* がコルーチンだった場合、自動的に Task としてスケジュールされま
   す。

   *timeout* には "None" もしくは待つ秒数の浮動小数点数か整数を指定で
   きます。 *timeout* が "None" の場合、 Future が完了するまで待ちます
   。

   タイムアウトが起きた場合は、 Task をキャンセルし
   "asyncio.TimeoutError" を送出します。

   Task の "キャンセル" を避けるためには、 "shield()" の中にラップして
   ください。

   この関数は future が実際にキャンセルされるまで待つため、待ち時間の
   合計は *timeout*  を超えることがあります。キャンセル中に例外が発生
   した場合は、その例外は伝達されます。

   待機が中止された場合 *aw* も中止されます。

   バージョン 3.10 で変更: *loop* パラメータが削除されました。

   以下はプログラム例です:

      async def eternity():
          # Sleep for one hour
          await asyncio.sleep(3600)
          print('yay!')

      async def main():
          # Wait for at most 1 second
          try:
              await asyncio.wait_for(eternity(), timeout=1.0)
          except asyncio.TimeoutError:
              print('timeout!')

      asyncio.run(main())

      # Expected output:
      #
      #     timeout!

   バージョン 3.7 で変更: *aw* がタイムアウトでキャンセルされたとき、
   "wait_for" は *aw* がキャンセルされるまで待ちます。 以前は、すぐに
   "asyncio.TimeoutError" を送出していました。

   バージョン 3.10 で変更: *loop* パラメータが削除されました。


要素の終了待機
==============

coroutine asyncio.wait(aws, *, timeout=None, return_when=ALL_COMPLETED)

   イテラブル *aws* 内の awaitable オブジェクト を並列実行し、
   *return_when* で与えられた条件が満たされるまで処理をブロックします
   。

   イテラブル *aws* は空であってはなりません。

   Task/Future からなる 2 つの集合 "(done, pending)" を返します。

   使い方:

      done, pending = await asyncio.wait(aws)

   *timeout* (浮動小数点数または整数) が指定されていたら、処理を返すの
   を待つ最大秒数を制御するのに使われます。

   この関数は "asyncio.TimeoutError" を送出しないことに注意してくださ
   い。 タイムアウトが起きたときに完了していなかった Future や Task は
   、2 つ目の集合の要素として返されるだけです。

   *return_when* でこの関数がいつ結果を返すか指定します。指定できる値
   は以下の 定数のどれか一つです:

   +-------------------------------+------------------------------------------+
   | 定数                          | 説明                                     |
   |===============================|==========================================|
   | "FIRST_COMPLETED"             | いずれかのフューチャが終了したかキャンセ |
   |                               | ルされたときに返します。                 |
   +-------------------------------+------------------------------------------+
   | "FIRST_EXCEPTION"             | いずれかのフューチャが例外の送出で終了し |
   |                               | た場合に返します。例外を送 出したフュー  |
   |                               | チャがない場合は、"ALL_COMPLETED" と等価 |
   |                               | になります。                             |
   +-------------------------------+------------------------------------------+
   | "ALL_COMPLETED"               | すべてのフューチャが終了したかキャンセル |
   |                               | されたときに返します。                   |
   +-------------------------------+------------------------------------------+

   "wait_for()" と異なり、  "wait()" はタイムアウトが起きたときに
   Future をキャンセルしません。

   バージョン 3.8 で非推奨: *aws* にある awaitable のどれかがコルーチ
   ンの場合、自動的に Task としてスケジュールされます。 コルーチンオブ
   ジェクトを "wait()" に直接渡すのは 紛らわしい振る舞い を引き起こす
   ため非推奨です。

   バージョン 3.10 で変更: *loop* パラメータが削除されました。

   注釈:

     "wait()" は自動的にコルーチンを Task としてスケジュールし、その後
     、暗黙的に作成された Task オブジェクトを組になった集合 "(done,
     pending)" に入れて返します。 従って、次のコードは予想した通りには
     動作しません:

        async def foo():
            return 42

        coro = foo()
        done, pending = await asyncio.wait({coro})

        if coro in done:
            # This branch will never be run!

     上のスクリプト片は次のように修正できます:

        async def foo():
            return 42

        task = asyncio.create_task(foo())
        done, pending = await asyncio.wait({task})

        if task in done:
            # Everything will work as expected now.

   バージョン 3.8 で非推奨、バージョン 3.11 で削除予定: "wait()" にコ
   ルーチンオブジェクトを直接渡すのは非推奨です。

   バージョン 3.10 で変更: *loop* パラメータが削除されました。

asyncio.as_completed(aws, *, timeout=None)

   イテラブル *aws* 内の awaitable オブジェクト を並列実行します。コル
   ーチンのイテレータを返します。戻り値の各コルーチンは、残りの
   awaitable のうちで最も早く得られた結果を待ち受けることができます。

   全フューチャが終了する前にタイムアウトが発生した場合
   "asyncio.TimeoutError" を送出します。

   以下はプログラム例です:

      for coro in as_completed(aws):
          earliest_result = await coro
          # ...

   バージョン 3.10 で変更: *loop* パラメータが削除されました。

   バージョン 3.10 で非推奨: Deprecation warning is emitted if not all
   awaitable objects in the *aws* iterable are Future-like objects and
   there is no running event loop.


スレッド内での実行
==================

coroutine asyncio.to_thread(func, /, *args, **kwargs)

   別のスレッドで非同期的に関数 *func* を実行します。

   この関数に渡された *args と **kwargs は関数 *func* に直接渡されます
   。また、イベントループスレッドのコンテキスト変数に関数を実行するス
   レッドからアクセスできるように、現在の "contextvars.Context" も伝播
   されます。

   関数 *func* の最終結果を待ち受けできるコルーチンを返します。

   このコルーチン関数は、メインスレッドで実行するとイベントループをブ
   ロックしてしまうような、 I/O バウンドな関数やメソッドに対して利用さ
   れることを主に想定しています。以下は使用例です:

      def blocking_io():
          print(f"start blocking_io at {time.strftime('%X')}")
          # Note that time.sleep() can be replaced with any blocking
          # IO-bound operation, such as file operations.
          time.sleep(1)
          print(f"blocking_io complete at {time.strftime('%X')}")

      async def main():
          print(f"started main at {time.strftime('%X')}")

          await asyncio.gather(
              asyncio.to_thread(blocking_io),
              asyncio.sleep(1))

          print(f"finished main at {time.strftime('%X')}")


      asyncio.run(main())

      # Expected output:
      #
      # started main at 19:50:53
      # start blocking_io at 19:50:53
      # blocking_io complete at 19:50:54
      # finished main at 19:50:54

   Directly calling "blocking_io()" in any coroutine would block the
   event loop for its duration, resulting in an additional 1 second of
   run time. Instead, by using "asyncio.to_thread()", we can run it in
   a separate thread without blocking the event loop.

   注釈:

     Due to the *GIL*, "asyncio.to_thread()" can typically only be
     used to make IO-bound functions non-blocking. However, for
     extension modules that release the GIL or alternative Python
     implementations that don't have one, "asyncio.to_thread()" can
     also be used for CPU-bound functions.

   バージョン 3.9 で追加.


外部スレッドからのスケジュール
==============================

asyncio.run_coroutine_threadsafe(coro, loop)

   与えられたイベントループにコルーチンを送ります。 この処理は、スレッ
   ドセーフです。

   他の OS スレッドから結果を待つための "concurrent.futures.Future" を
   返します。

   この関数は、イベントループが動作しているスレッドとは異なる OS スレ
   ッドから呼び出すためのものです。 例えば次のように使います:

      # Create a coroutine
      coro = asyncio.sleep(1, result=3)

      # Submit the coroutine to a given loop
      future = asyncio.run_coroutine_threadsafe(coro, loop)

      # Wait for the result with an optional timeout argument
      assert future.result(timeout) == 3

   コルーチンから例外が送出された場合、返された Future に通知されます
   。 これはイベントループの Task をキャンセルするのにも使えます:

      try:
          result = future.result(timeout)
      except concurrent.futures.TimeoutError:
          print('The coroutine took too long, cancelling the task...')
          future.cancel()
      except Exception as exc:
          print(f'The coroutine raised an exception: {exc!r}')
      else:
          print(f'The coroutine returned: {result!r}')

   このドキュメントの 並行処理とマルチスレッド処理 節を参照してくださ
   い。

   他の asyncio 関数とは異なり、この関数は明示的に渡される *loop* 引数
   を必要とします。

   バージョン 3.5.1 で追加.


イントロスペクション
====================

asyncio.current_task(loop=None)

   現在実行中の "Task" インスタンスを返します。実行中の Task が無い場
   合は "None" を返します。

   *loop* が "None" の場合、 "get_running_loop()" が現在のループを取得
   するのに使われます。

   バージョン 3.7 で追加.

asyncio.all_tasks(loop=None)

   ループで実行された "Task" オブジェクトでまだ完了していないものの集
   合を返します。

   *loop* が "None" の場合、 "get_running_loop()" は現在のループを取得
   するのに使われます。

   バージョン 3.7 で追加.


Task オブジェクト
=================

class asyncio.Task(coro, *, loop=None, name=None)

   Python コルーチン を実行する "Future 類" オブジェクトです。 スレッ
   ドセーフではありません。

   Task はイベントループのコルーチンを実行するのに使われます。 Future
   でコルーチンが待機している場合、 Task は自身のコルーチンの実行を一
   時停止させ、 Future の完了を待ちます。 Future が *完了* したら、
   Task が内包しているコルーチンの実行を再開します。

   イベントループは協調スケジューリングを使用します。つまり、イベント
   ループは同時に 1 つの Task のみ実行します。 Task が Future の完了を
   待っているときは、イベントループは他の Task やコールバックを動作さ
   せるか、 IO 処理を実行します。

   Task を作成するには高レベルの "asyncio.create_task()" 関数、あるい
   は低レベルの "loop.create_task()" 関数や "ensure_future()" 関数を使
   用してください。 手作業での Task の実装は推奨されません。

   実行中のタスクをキャンセルするためには、"cancel()" メソッドを使用し
   ます。このメソッドを呼ぶと、タスクはそれを内包するコルーチンに対し
   て "CancelledError" 例外を送出します。キャンセルの際にコルーチンが
   Future オブジェクトを待っていた場合、その Future オブジェクトはキャ
   ンセルされます。

   "cancelled()" は、タスクがキャンセルされたかを調べるのに使用できま
   す。タスクを内包するコルーチンで "CancelledError" 例外が抑制されて
   おらず、かつタスクが実際にキャンセルされている場合に、このメソッド
   は "True" を変えます。

   "asyncio.Task" は、"Future.set_result()" と
   "Future.set_exception()" を除いて、"Future" の API をすべて継承して
   います。

   Task は "contextvars" モジュールをサポートします。Task が作られたと
   きに現在のコンテキストがコピーされ、のちに Task のコルーチンを実行
   する際に、コピーされたコンテキストが使用されます。

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

   バージョン 3.8 で変更: *name* パラメータを追加しました。

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

   cancel(msg=None)

      このタスクに、自身のキャンセルを要求します。

      このメソッドは、イベントループの次のステップにおいて、タスクがラ
      ップしているコルーチン内で "CancelledError" 例外が送出されるよう
      に準備します。

      コルーチン側では "try" ... ... "except CancelledError" ...
      "finally" ブロックで例外を処理することにより、クリーンアップ処理
      を行なったり、リクエストを拒否したりする機会が与えられます。この
      特性を使ってキャンセル処理を完全に抑え込むことも可能であることか
      ら、 "Future.cancel()" と異なり、 "Task.cancel()" は Task が実際
      にキャンセルされることを保証しません。ただしそのような処理は一般
      的ではありませんし、そのような処理をしないことが望ましいです。

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

      以下の例は、コルーチンがどのようにしてキャンセルのリクエストを阻
      止するかを示しています:

         async def cancel_me():
             print('cancel_me(): before sleep')

             try:
                 # Wait for 1 hour
                 await asyncio.sleep(3600)
             except asyncio.CancelledError:
                 print('cancel_me(): cancel sleep')
                 raise
             finally:
                 print('cancel_me(): after sleep')

         async def main():
             # Create a "cancel_me" Task
             task = asyncio.create_task(cancel_me())

             # Wait for 1 second
             await asyncio.sleep(1)

             task.cancel()
             try:
                 await task
             except asyncio.CancelledError:
                 print("main(): cancel_me is cancelled now")

         asyncio.run(main())

         # Expected output:
         #
         #     cancel_me(): before sleep
         #     cancel_me(): cancel sleep
         #     cancel_me(): after sleep
         #     main(): cancel_me is cancelled now

   cancelled()

      Task が *キャンセルされた* 場合に "True" を返します。

      "cancel()" メソッドによりキャンセルがリクエストされ、かつ Task
      がラップしているコルーチンが内部で送出された "CancelledError" 例
      外を伝達したとき、 Task は実際に *キャンセル* されます。

   done()

      Task が *完了* しているなら "True" を返します。

      Task がラップしているコルーチンが値を返すか、例外を送出するか、
      または Task がキャンセルされたとき、 Task は *完了* します。

   result()

      Task の結果を返します。

      Task が *完了* している場合、ラップしているコルーチンの結果が返
      されます (コルーチンが例外を送出された場合、その例外が例外が再送
      出されます)

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

      Task の結果がまだ未設定の場合、このメソッドは
      "InvalidStateError" 例外を送出します。

   exception()

      Task の例外を返します。

      ラップされたコルーチンが例外を送出した場合、その例外が返されます
      。ラップされたコルーチンが正常終了した場合、このメソッドは
      "None" を返します。

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

      Task がまだ *完了* していない場合、このメソッドは
      "InvalidStateError" 例外を送出します。

   add_done_callback(callback, *, context=None)

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

      このメソッドは低水準のコールバックベースのコードでのみ使うべきで
      す。

      詳細については "Future.add_done_callback()" のドキュメントを参照
      してください。

   remove_done_callback(callback)

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

      このメソッドは低水準のコールバックベースのコードでのみ使うべきで
      す。

      詳細については "Future.remove_done_callback()" のドキュメントを
      参照してください。

   get_stack(*, limit=None)

      このタスクのスタックフレームのリストを返します。

      コルーチンが完了していない場合、これはサスペンドされた時点でのス
      タックを返します。コルーチンが正常に処理を完了したか、キャンセル
      されていた場合は空のリストを返します。コルーチンが例外で終了した
      場合はトレースバックフレームのリストを返します。

      フレームは常に古いものから新しい物へ並んでいます。

      サスペンドされているコルーチンの場合スタックフレームが 1 個だけ
      返されます。

      オプション引数 *limit* は返すフレームの最大数を指定します; デフ
      ォルトでは取得可能な全てのフレームを返します。返されるリストの順
      番は、スタックが返されるか、トレースバックが返されるかによって変
      わります: スタックでは新しい順に並んだリストが返されますが、トレ
      ースバックでは古い順に並んだリストが返されます（これは traceback
      モジュールの振る舞いと一致します）。

   print_stack(*, limit=None, file=None)

      このタスクのスタックまたはトレースバックを出力します。

      このメソッドは "get_stack()" によって取得されるフレームに対し、
      traceback モジュールと同じような出力を生成します。

      引数 *limit* は "get_stack()" にそのまま渡されます。

      The *file* argument is an I/O stream to which the output is
      written; by default output is written to "sys.stdout".

   get_coro()

      "Task" がラップしているコルーチンオブジェクトを返します。

      バージョン 3.8 で追加.

   get_name()

      Task の名前を返します。

      Task に対して明示的に名前が設定されていない場合, デフォルトの
      asyncio Task 実装はタスクをインスタンス化する際にデフォルトの名
      前を生成します。

      バージョン 3.8 で追加.

   set_name(value)

      Task に名前を設定します。

      引数 *value* は文字列に変換可能なオブジェクトであれば何でもかま
      いません。

      Task のデフォルト実装では、名前はオブジェクトの "repr()" メソッ
      ドの出力で確認できます。

      バージョン 3.8 で追加.


ジェネレータベースのコルーチン
==============================

注釈:

  Support for generator-based coroutines is **deprecated** and is
  removed in Python 3.11.

ジェネレータベースのコルーチンは async/await シンタックスに先行して登
場しました。これは "yield from" 式を使って Future または他のコルーチン
を待ち受ける Python ジェネレータです。

強制ではありませんが、ジェネレータベースのコルーチンは
"@asyncio.coroutine" でデコレートされるべきです。

@asyncio.coroutine

   ジェネレータベースのコルーチンであることを示すデコレータです。

   このデコレータはレガシー機能であるジェネレータベースのコルーチンを
   async/await コードと互換にします:

      @asyncio.coroutine
      def old_style_coroutine():
          yield from asyncio.sleep(1)

      async def main():
          await old_style_coroutine()

   このデコレータは "async def" で定義されるコルーチンに使用すべきでは
   ありません。

   バージョン 3.8 で非推奨、バージョン 3.11 で削除予定: 代わりに
   "async def" を使ってください。

asyncio.iscoroutine(obj)

   *obj* が コルーチンオブジェクト であれば "True" を返します。

   このメソッドはジェネレータベースのコルーチンに対しても "True" を返
   すので、 "inspect.iscoroutine()" とは異なります。

asyncio.iscoroutinefunction(func)

   Return "True" if *func* is a coroutine function.

   このメソッドは "@coroutine" でデコレートされたジェネレータベースの
   コルーチン関数に対しても "True" を返すため、
   "inspect.iscoroutinefunction()" とは異なります。
