18.5.3。 タスクとコルーチン
ソースコード: :source: `Lib / asyncio / tasks.py`
ソースコード: :source: `Lib / asyncio / coroutines.py`
18.5.3.1。 コルーチン
asyncio で使用されるコルーチンは、 async def ステートメントを使用するか、ジェネレーターを使用して実装できます。 async def タイプのコルーチンがPython3.5で追加されたため、古いバージョンのPythonをサポートする必要がない場合に推奨されます。
ジェネレータベースのコルーチンは、 @ asyncio.coroutine で装飾する必要がありますが、これは厳密には強制されません。 デコレータは、 async def コルーチンとの互換性を可能にし、ドキュメントとしても機能します。 ジェネレータベースのコルーチンは、元のyield
構文の代わりに、 PEP 380 で導入されたyield from
構文を使用します。
「コルーチン」という単語は、「ジェネレーター」という単語と同様に、2つの異なる(関連はあるものの)概念に使用されます。
- コルーチンを定義する関数( async def を使用するか、
@asyncio.coroutine
で装飾された関数定義)。 曖昧性解消が必要な場合は、これをコルーチン関数と呼びます( iscoroutinefunction()はTrue
を返します)。 - コルーチン関数を呼び出して取得したオブジェクト。 このオブジェクトは、最終的に完了する計算またはI / O操作(通常は組み合わせ)を表します。 曖昧性解消が必要な場合は、コルーチンオブジェクトと呼びます( iscoroutine()は
True
を返します)。
コルーチンでできること:
result = await future
またはresult = yield from future
–フューチャーが完了するまでコルーチンを一時停止してから、フューチャーの結果を返すか、例外を発生させて伝播します。 (先物がキャンセルされると、CancelledError
例外が発生します。)タスクは先物であり、先物について述べられていることはすべてタスクにも当てはまることに注意してください。result = await coroutine
またはresult = yield from coroutine
–別のコルーチンが結果を生成するのを待ちます(または例外を発生させます。これは伝播されます)。coroutine
式は、別のコルーチンへの呼び出しである必要があります。return expression
– await またはyield from
を使用して、これを待機しているコルーチンに結果を生成します。raise exception
– await またはyield from
を使用して、これを待機しているコルーチンで例外を発生させます。
コルーチンを呼び出しても、コードの実行は開始されません。呼び出しによって返されるコルーチンオブジェクトは、実行をスケジュールするまで何も実行しません。 実行を開始するには、2つの基本的な方法があります。別のコルーチンからawait coroutine
またはyield from coroutine
を呼び出すか(他のコルーチンがすでに実行されていると仮定)、 ensure_future()を使用して実行をスケジュールします。 関数または AbstractEventLoop.create_task()メソッド。
コルーチン(およびタスク)は、イベントループが実行されている場合にのみ実行できます。
- @asyncio.coroutine
ジェネレータベースのコルーチンをマークするデコレータ。 これにより、ジェネレーターは
yield from
を使用して async def コルーチンを呼び出すことができます。また、ジェネレーターを async def コルーチンから呼び出すこともできます。たとえば、 awaitを使用します。 式。async def コルーチン自体を装飾する必要はありません。
ジェネレーターが破棄される前から生成されていない場合は、エラーメッセージがログに記録されます。 スケジュールされていないコルーチンの検出を参照してください。
ノート
このドキュメントでは、 Future を返すプレーンなPython関数であっても、一部のメソッドはコルーチンとしてドキュメント化されています。 これは、将来これらの機能の実装を自由に調整できるようにすることを目的としています。 このような関数をコールバックスタイルのコードで使用する必要がある場合は、その結果を ensure_future()でラップします。
18.5.3.1.1。 例:HelloWorldコルーチン
"Hello World"
を表示するコルーチンの例:
18.5.3.1.2。 例:現在の日付を表示するコルーチン
sleep()
関数を使用して、現在の日付を5秒間毎秒表示するコルーチンの例:
18.5.3.1.3。 例:チェーンコルーチン
コルーチンの連鎖の例:
compute()
はprint_sum()
にチェーンされます:print_sum()
コルーチンは、compute()
が完了するまで待機してから結果を返します。
例のシーケンス図:
class=align-center|../_images/tulip_coro.png 「タスク」は、タスクではなくコルーチンオブジェクトを取得するときに、 AbstractEventLoop.run_until_complete()メソッドによって作成されます。
この図は制御フローを示していますが、内部でどのように機能するかを正確に説明しているわけではありません。 たとえば、スリープコルーチンは、 AbstractEventLoop.call_later()を使用して1秒でタスクをウェイクアップする内部フューチャーを作成します。
18.5.3.2。 InvalidStateError
- exception asyncio.InvalidStateError
- この状態では操作できません。
18.5.3.3。 TimeoutError
- exception asyncio.TimeoutError
- 操作が指定された期限を超えました。
18.5.3.4。 未来
- class asyncio.Future(\*, loop=None)
このクラスはほぼと concurrent.futures.Future と互換性があります。
違い:
result()および exception()は、タイムアウト引数をとらず、futureがまだ完了していないときに例外を発生させます。
add_done_callback()で登録されたコールバックは、常にイベントループの call_soon()を介して呼び出されます。
このクラスは、 concurrent.futures パッケージの wait()および as_completed()関数と互換性がありません。
このクラスはスレッドセーフではありません。
- cancel()
将来をキャンセルし、コールバックをスケジュールします。
将来がすでに完了またはキャンセルされている場合は、
False
を返します。 それ以外の場合は、futureの状態をキャンセルに変更し、コールバックをスケジュールして、True
を返します。
- cancelled()
将来がキャンセルされた場合は、
True
を返します。
- done()
将来が完了した場合は、
True
を返します。完了とは、結果/例外が利用可能であるか、将来がキャンセルされたことを意味します。
- result()
この未来が表す結果を返します。
未来がキャンセルされた場合、
CancelledError
を上げます。 将来の結果がまだ利用できない場合は、 InvalidStateError を発生させます。 futureが実行され、例外が設定されている場合、この例外が発生します。
- exception()
この未来に設定された例外を返します。
例外(または例外が設定されていない場合は
None
)は、futureが実行された場合にのみ返されます。 未来がキャンセルされた場合、CancelledError
を上げます。 将来がまだ完了していない場合は、 InvalidStateError を発生させます。
- add_done_callback(fn)
将来が完了したときに実行されるコールバックを追加します。
コールバックは、単一の引数(futureオブジェクト)で呼び出されます。 これが呼び出されたときにfutureがすでに実行されている場合、コールバックは call_soon()でスケジュールされます。
functools.partialを使用して、コールバックにパラメーターを渡します。 たとえば、
fut.add_done_callback(functools.partial(print, "Future:", flush=True))
はprint("Future:", fut, flush=True)
を呼び出します。
- remove_done_callback(fn)
「完了時の呼び出し」リストからコールバックのすべてのインスタンスを削除します。
削除されたコールバックの数を返します。
- set_result(result)
完了した未来をマークし、その結果を設定します。
このメソッドが呼び出されたときにfutureがすでに実行されている場合は、 InvalidStateError が発生します。
- set_exception(exception)
完了をマークし、例外を設定します。
このメソッドが呼び出されたときにfutureがすでに実行されている場合は、 InvalidStateError が発生します。
18.5.3.4.1。 例:run_until_complete()を使用したFuture
コルーチン関数は計算(1秒かかります)を担当し、結果を将来に保存します。 run_until_complete()メソッドは、futureの完了を待ちます。
18.5.3.4.2。 例:run_forever()を使用したFuture
前の例は、 Future.add_done_callback()メソッドを使用して別の方法で記述し、制御フローを明示的に記述することができます。
この例では、futureを使用してslow_operation()
をgot_result()
にリンクしています。slow_operation()
が完了すると、got_result()
が呼び出されて結果が返されます。
18.5.3.5。 タスク
- class asyncio.Task(coro, \*, loop=None)
コルーチンの実行をスケジュールします。将来的にラップします。 タスクは Future のサブクラスです。
タスクは、イベントループでコルーチンオブジェクトを実行する責任があります。 ラップされたコルーチンがfutureから派生した場合、タスクはラップされたコルーチンの実行を一時停止し、futureの完了を待ちます。 futureが完了すると、ラップされたコルーチンの実行が再開され、futureの結果または例外が発生します。
イベントループは協調スケジューリングを使用します。イベントループは一度に1つのタスクのみを実行します。 他のイベントループが異なるスレッドで実行されている場合、他のタスクが並行して実行される可能性があります。 タスクがfutureの完了を待機している間、イベントループは新しいタスクを実行します。
タスクのキャンセルは、将来のキャンセルとは異なります。 cancel()を呼び出すと、ラップされたコルーチンに CancelledError がスローされます。 cancelled()は、ラップされたコルーチンが CancelledError 例外をキャッチしなかった場合、または CancelledError 例外を発生させた場合にのみ、
True
を返します。保留中のタスクが破棄された場合、ラップされたコルーチンの実行は完了しませんでした。 これはおそらくバグであり、警告がログに記録されます。保留中のタスクが破棄されましたを参照してください。
Task インスタンスを直接作成しないでください。 ensure_future()関数または AbstractEventLoop.create_task()メソッドを使用してください。
このクラスはスレッドセーフではありません。
- classmethod all_tasks(loop=None)
イベントループのすべてのタスクのセットを返します。
デフォルトでは、現在のイベントループのすべてのタスクが返されます。
- classmethod current_task(loop=None)
現在実行中のタスクをイベントループまたは
None
で返します。デフォルトでは、現在のイベントループの現在のタスクが返されます。
None
は、タスクのコンテキストではなく呼び出されたときに返されます。
- cancel()
このタスクが自動的にキャンセルされるように要求します。
これにより、 CancelledError が、イベントループの次のサイクルでラップされたコルーチンにスローされるようになります。 その後、コルーチンは、try / exception / finallyを使用してリクエストをクリーンアップまたは拒否する機会があります。
Future.cancel()とは異なり、これはタスクがキャンセルされることを保証するものではありません。例外がキャッチされて処理され、タスクのキャンセルが遅れたり、キャンセルが完全に妨げられたりする可能性があります。 タスクは、値を返したり、別の例外を発生させたりする場合もあります。
このメソッドが呼び出された直後、 cancelled()は
True
を返しません(タスクがすでにキャンセルされていない限り)。 ラップされたコルーチンが CancelledError 例外で終了すると、タスクはキャンセル済みとしてマークされます( cancel()が呼び出されなかった場合でも)。
- get_stack(\*, limit=None)
このタスクのコルーチンのスタックフレームのリストを返します。
コルーチンが実行されていない場合、これは中断されているスタックを返します。 コルーチンが正常に完了したかキャンセルされた場合、これは空のリストを返します。 コルーチンが例外によって終了した場合、これはトレースバックフレームのリストを返します。
フレームは常に古いものから新しいものの順に並べられます。
オプションの制限は、返すフレームの最大数を示します。 デフォルトでは、使用可能なすべてのフレームが返されます。 その意味は、スタックとトレースバックのどちらが返されるかによって異なります。スタックの最新のフレームが返されますが、トレースバックの最も古いフレームが返されます。 (これは、トレースバックモジュールの動作と一致します。)
制御できない理由により、中断されたコルーチンに対して1つのスタックフレームのみが返されます。
- print_stack(\*, limit=None, file=None)
このタスクのコルーチンのスタックまたはトレースバックを印刷します。
これにより、get_stack()によって取得されたフレームに対して、トレースバックモジュールと同様の出力が生成されます。 limit引数はget_stack()に渡されます。 file引数は、出力が書き込まれるI / Oストリームです。 デフォルトでは、出力はsys.stderrに書き込まれます。
18.5.3.5.1。 例:タスクの並列実行
3つのタスク(A、B、C)を並行して実行する例:
出力:
タスクは、作成時に自動的に実行がスケジュールされます。 すべてのタスクが完了すると、イベントループが停止します。
18.5.3.6。 タスク機能
ノート
以下の関数では、オプションの loop 引数を使用して、基になるタスクまたはコルーチンで使用されるイベントループオブジェクトを明示的に設定できます。 指定されていない場合は、デフォルトのイベントループが使用されます。
- asyncio.as_completed(fs, \*, loop=None, timeout=None)
待機時に値が Future インスタンスであるイテレータを返します。
すべての先物が完了する前にタイムアウトが発生した場合、 asyncio.TimeoutError を発生させます。
例:
ノート
先物
f
は必ずしもfsのメンバーではありません。
- asyncio.ensure_future(coro_or_future, \*, loop=None)
コルーチンオブジェクトの実行をスケジュールします。将来的にラップします。 Task オブジェクトを返します。
引数が Future の場合、直接返されます。
バージョン3.4.4の新機能。
バージョン3.5.1で変更:この関数は、待機可能なオブジェクトを受け入れます。
も参照してください
- asyncio.async(coro_or_future, \*, loop=None)
ensure_future()の非推奨のエイリアス。
バージョン3.4.4以降非推奨。
- asyncio.wrap_future(future, \*, loop=None)
- concurrent.futures.Future オブジェクトを Future オブジェクトでラップします。
- asyncio.gather(\*coros_or_futures, loop=None, return_exceptions=False)
指定されたコルーチンオブジェクトまたは先物からの先物集計結果を返します。
すべての先物は同じイベントループを共有する必要があります。 すべてのタスクが正常に実行された場合、返されるfutureの結果は結果のリストです(元のシーケンスの順序であり、必ずしも結果の到着の順序である必要はありません)。 return_exceptions がtrueの場合、タスクの例外は成功した結果と同じように扱われ、結果リストに収集されます。 それ以外の場合、最初に発生した例外は、返されたfutureにすぐに伝播されます。
キャンセル:外側のFutureがキャンセルされると、(まだ完了していない)すべての子もキャンセルされます。 いずれかの子がキャンセルされた場合、これは CancelledError を発生させたかのように扱われます。この場合、外側のFutureはキャンセルされません。 (これは、1人の子がキャンセルされて他の子がキャンセルされるのを防ぐためです。)
バージョン3.6.6で変更: collect 自体がキャンセルされた場合、 return_exceptions に関係なくキャンセルが伝播されます。
- asyncio.iscoroutine(obj)
- obj がコルーチンオブジェクトの場合は
True
を返します。これは、ジェネレーターまたは async def コルーチンに基づいている可能性があります。
- asyncio.iscoroutinefunction(func)
- func がコルーチン関数であると判断された場合は
True
を返します。これは、装飾されたジェネレーター関数または async def 関数である可能性があります。
- asyncio.run_coroutine_threadsafe(coro, loop)
コルーチンオブジェクトを特定のイベントループに送信します。
結果にアクセスするには、 concurrent.futures.Future を返します。
この関数は、イベントループが実行されているスレッドとは異なるスレッドから呼び出されることを意図しています。 使用法:
コルーチンで例外が発生した場合、返される未来が通知されます。 また、イベントループでタスクをキャンセルするために使用することもできます。
ドキュメントの同時実行およびマルチスレッドセクションを参照してください。
ノート
モジュールの他の関数とは異なり、 run_coroutine_threadsafe()では、 loop 引数を明示的に渡す必要があります。
バージョン3.5.1の新機能。