イベントループ
ソースコード: :source: `Lib / asyncio / events.py`, :source: `Lib / asyncio / base_events.py`
序文
イベントループは、すべてのasyncioアプリケーションの中核です。 イベントループは、非同期タスクとコールバックを実行し、ネットワークIO操作を実行し、サブプロセスを実行します。
アプリケーション開発者は通常、 asyncio.run()などの高レベルの非同期関数を使用する必要があり、ループオブジェクトを参照したりそのメソッドを呼び出したりする必要はほとんどありません。 このセクションは主に、イベントループの動作をより細かく制御する必要がある、低レベルのコード、ライブラリ、およびフレームワークの作成者を対象としています。
イベントループの取得
次の低レベル関数を使用して、イベントループを取得、設定、または作成できます。
- asyncio.get_running_loop()
現在のOSスレッドで実行中のイベントループを返します。
実行中のイベントループがない場合、 RuntimeError が発生します。 この関数は、コルーチンまたはコールバックからのみ呼び出すことができます。
バージョン3.7の新機能。
- asyncio.get_event_loop()
現在のイベントループを取得します。
現在のOSスレッドに現在のイベントループが設定されておらず、OSスレッドがメインであり、 set_event_loop()がまだ呼び出されていない場合、asyncioは新しいイベントループを作成し、それを現在のイベントループとして設定します。
この関数の動作はかなり複雑であるため(特にカスタムイベントループポリシーが使用されている場合)、コルーチンとコールバックでは get_event_loop()よりも get_running_loop()関数を使用することをお勧めします。
低レベルの関数を使用してイベントループを手動で作成および閉じる代わりに、 asyncio.run()関数を使用することも検討してください。
- asyncio.set_event_loop(loop)
- loop を現在のOSスレッドの現在のイベントループとして設定します。
- asyncio.new_event_loop()
- 新しいイベントループオブジェクトを作成します。
get_event_loop()、 set_event_loop()、および new_event_loop()関数の動作は、カスタムイベントループポリシーを設定することで変更できることに注意してください[ X177X]。
コンテンツ
このドキュメントページには、次のセクションが含まれています。
- イベントループメソッドセクションは、イベントループAPIのリファレンスドキュメントです。
- コールバックハンドルセクションには、 loop.call_soon()やなどのスケジューリングメソッドから返される Handle および TimerHandle インスタンスが記載されています。 ] loop.call_later();
- サーバーオブジェクトセクションには、
loop.create_server()
などのイベントループメソッドから返されるタイプが記載されています。 - イベントループの実装セクションには、 SelectorEventLoop および ProactorEventLoop クラスが記載されています。
- の例セクションでは、いくつかのイベントループAPIを操作する方法を紹介しています。
イベントループメソッド
イベントループには、次の低レベル APIがあります。
- ループの実行と停止
- コールバックのスケジュール
- 遅延コールバックのスケジュール
- 先物とタスクの作成
- ネットワーク接続を開く
- ネットワークサーバーの作成
- ファイルの転送
- TLSアップグレード
- ファイル記述子の監視
- ソケットオブジェクトを直接操作する
- DNS
- パイプの操作
- Unixシグナル
- スレッドまたはプロセスプールでコードを実行する
- エラー処理API
- デバッグモードの有効化
- サブプロセスの実行
ループの実行と停止
- loop.run_until_complete(future)
future ( Future のインスタンス)が完了するまで実行します。
引数がコルーチンオブジェクトの場合、 asyncio.Task として実行するように暗黙的にスケジュールされます。
Futureの結果を返すか、その例外を発生させます。
- loop.run_forever()
stop()が呼び出されるまで、イベントループを実行します。
run_forever()が呼び出される前に stop()が呼び出された場合、ループはタイムアウトゼロでI / Oセレクターを1回ポーリングし、I /に応答してスケジュールされたすべてのコールバックを実行します。 Oイベント(およびすでにスケジュールされているイベント)を実行して、終了します。
run_forever()の実行中に stop()が呼び出されると、ループは現在のコールバックのバッチを実行して終了します。 この場合、コールバックによってスケジュールされた新しいコールバックは実行されないことに注意してください。 代わりに、次に run_forever()または run_until_complete()が呼び出されたときに実行されます。
- loop.stop()
- イベントループを停止します。
- loop.is_running()
- イベントループが現在実行中の場合は、
True
を返します。
- loop.is_closed()
- イベントループが閉じられた場合は、
True
を返します。
- loop.close()
イベントループを閉じます。
この関数を呼び出すときは、ループを実行してはなりません。 保留中のコールバックはすべて破棄されます。
このメソッドは、すべてのキューをクリアしてエグゼキュータをシャットダウンしますが、エグゼキュータが終了するのを待ちません。
この方法はべき等で不可逆的です。 イベントループが閉じられた後は、他のメソッドを呼び出さないでください。
コールバックのスケジュール
- loop.call_soon(callback, *args, context=None)
callback callback が、イベントループの次の反復で args 引数を使用して呼び出されるようにスケジュールします。
コールバックは、登録された順序で呼び出されます。 各コールバックは1回だけ呼び出されます。
オプションのキーワードのみの context 引数を使用すると、コールバックを実行するカスタム contextvars.Context を指定できます。 現在のコンテキストは、 context が提供されていない場合に使用されます。
asyncio.Handle のインスタンスが返されます。これは、後でコールバックをキャンセルするために使用できます。
この方法はスレッドセーフではありません。
- loop.call_soon_threadsafe(callback, *args, context=None)
call_soon()のスレッドセーフなバリアント。 別のスレッドからのコールバックをスケジュールするために使用する必要があります。
閉じられたループで呼び出された場合、 RuntimeError を発生させます。 これは、メインアプリケーションがシャットダウンしているときにセカンダリスレッドで発生する可能性があります。
ドキュメントの同時実行およびマルチスレッドセクションを参照してください。
バージョン3.7で変更: context キーワードのみのパラメーターが追加されました。 詳細については、 PEP 567 を参照してください。
ノート
ほとんどの asyncio スケジューリング関数は、キーワード引数の受け渡しを許可していません。 これを行うには、 functools.partial()を使用します。
asyncioはデバッグメッセージやエラーメッセージで部分オブジェクトをより適切にレンダリングできるため、通常、部分オブジェクトを使用する方がラムダを使用するよりも便利です。
遅延コールバックのスケジュール
イベントループは、将来のある時点で呼び出されるコールバック関数をスケジュールするメカニズムを提供します。 イベントループは、単調なクロックを使用して時間を追跡します。
- loop.call_later(delay, callback, *args, context=None)
指定された delay 秒数(intまたはfloatのいずれか)の後に呼び出されるように callback をスケジュールします。
asyncio.TimerHandle のインスタンスが返され、これを使用してコールバックをキャンセルできます。
コールバックは1回だけ呼び出されます。 2つのコールバックがまったく同じ時間にスケジュールされている場合、それらが呼び出される順序は定義されていません。
オプションの定位置 args は、呼び出されたときにコールバックに渡されます。 キーワード引数を使用してコールバックを呼び出す場合は、 functools.partial()を使用します。
オプションのキーワードのみの context 引数を使用すると、コールバックを実行するカスタム contextvars.Context を指定できます。 現在のコンテキストは、 context が提供されていない場合に使用されます。
バージョン3.7で変更: context キーワードのみのパラメーターが追加されました。 詳細については、 PEP 567 を参照してください。
バージョン3.8で変更:デフォルトのイベントループ実装を備えたPython 3.7以前では、 delay は1日を超えることはできませんでした。 これはPython3.8で修正されています。
- loop.call_at(when, callback, *args, context=None)
loop.time()と同じ時間参照を使用して、コールバックが指定された絶対タイムスタンプ when (intまたはfloat)で呼び出されるようにスケジュールします。
このメソッドの動作は、 call_later()と同じです。
asyncio.TimerHandle のインスタンスが返され、これを使用してコールバックをキャンセルできます。
バージョン3.7で変更: context キーワードのみのパラメーターが追加されました。 詳細については、 PEP 567 を参照してください。
バージョン3.8で変更:デフォルトのイベントループ実装を備えたPython 3.7以前では、 when と現在の時刻の差は1日を超えることはできませんでした。 これはPython3.8で修正されています。
- loop.time()
- イベントループの内部単調クロックに従って、現在の時刻を float 値として返します。
ノート
バージョン3.8で変更: Python 3.7以前では、タイムアウト(相対遅延または絶対の場合)は1日を超えてはなりません。 これはPython3.8で修正されています。
も参照してください
asyncio.sleep()
機能。
先物とタスクの作成
- loop.create_future()
イベントループにアタッチされた asyncio.Future オブジェクトを作成します。
これは、asyncioでFuturesを作成するための推奨される方法です。 これにより、サードパーティのイベントループがFutureオブジェクトの代替実装を提供できるようになります(パフォーマンスまたはインストルメンテーションが向上します)。
バージョン3.5.2の新機能。
- loop.create_task(coro, *, name=None)
コルーチンの実行をスケジュールします。 Task オブジェクトを返します。
サードパーティのイベントループは、相互運用性のために Task の独自のサブクラスを使用できます。 この場合、結果タイプは Task のサブクラスです。
name 引数が
None
ではなく指定されている場合、 Task.set_name()を使用してタスクの名前として設定されます。バージョン3.8で変更:
name
パラメーターが追加されました。
- loop.set_task_factory(factory)
loop.create_task()で使用されるタスクファクトリを設定します。
factory が
None
の場合、デフォルトのタスクファクトリが設定されます。 それ以外の場合、 factory は、(loop, coro)
と一致する署名を持つ callable である必要があります。ここで、 loop はアクティブなイベントループへの参照であり、[X160X ] coro はコルーチンオブジェクトです。 呼び出し可能オブジェクトは、 asyncio.Future 互換オブジェクトを返す必要があります。
- loop.get_task_factory()
- タスクファクトリを返すか、デフォルトのものが使用されている場合は
None
を返します。
ネットワーク接続を開く
ネットワークサーバーの作成
ファイルの転送
TLSアップグレード
ファイル記述子の監視
- loop.add_reader(fd, callback, *args)
- fd ファイル記述子の読み取り可能性の監視を開始し、 fd が読み取り可能になったら、指定された引数を使用してコールバックを呼び出します。
- loop.remove_reader(fd)
- fd ファイル記述子の読み取りの可用性の監視を停止します。
- loop.add_writer(fd, callback, *args)
fd ファイル記述子の書き込み可能性の監視を開始し、 fd が書き込み可能になったら、指定された引数を使用してコールバックを呼び出します。
functools.partial() を使用して、キーワード引数をコールバックに渡します。
- loop.remove_writer(fd)
- fd ファイル記述子の書き込み可能性の監視を停止します。
これらのメソッドのいくつかの制限については、プラットフォームサポートセクションも参照してください。
ソケットオブジェクトを直接操作する
一般に、loop.create_connection()
やloop.create_server()
などのトランスポートベースのAPIを使用するプロトコルの実装は、ソケットを直接操作する実装よりも高速です。 ただし、パフォーマンスが重要ではないユースケースがいくつかあり、 socket オブジェクトを直接操作する方が便利です。
DNS
バージョン3.7で変更: getaddrinfo メソッドと getnameinfo メソッドの両方が常にコルーチンを返すように文書化されていましたが、Python 3.7より前は、実際には[X192X ] asyncio.Future オブジェクト。 Python 3.7以降、どちらの方法もコルーチンです。
パイプの操作
も参照してください
loop.subprocess_exec()
およびloop.subprocess_shell()
メソッド。
Unixシグナル
- loop.add_signal_handler(signum, callback, *args)
callback を signum 信号のハンドラーとして設定します。
コールバックは、 loop によって、他のキューに入れられたコールバックおよびそのイベントループの実行可能なコルーチンとともに呼び出されます。 signal.signal()を使用して登録されたシグナルハンドラーとは異なり、この関数に登録されたコールバックは、イベントループと対話できます。
シグナル番号が無効またはキャッチできない場合は、 ValueError を発生させます。 ハンドラーの設定に問題がある場合は、 RuntimeError を発生させます。
functools.partial() を使用して、キーワード引数をコールバックに渡します。
signal.signal()と同様に、この関数はメインスレッドで呼び出す必要があります。
- loop.remove_signal_handler(sig)
sig 信号のハンドラーを削除します。
シグナルハンドラーが削除された場合は
True
を返し、指定されたシグナルにハンドラーが設定されていない場合はFalse
を返します。
スレッドまたはプロセスプールでコードを実行する
- loop.set_default_executor(executor)
executor を、
run_in_executor()
が使用するデフォルトのエグゼキュータとして設定します。 executer は、 ThreadPoolExecutor のインスタンスである必要があります。バージョン3.8以降非推奨: ThreadPoolExecutor のインスタンスではないエグゼキューターの使用は非推奨になり、Python3.9でエラーがトリガーされます。
executer は、 concurrent.futures.ThreadPoolExecutor のインスタンスである必要があります。
エラー処理API
イベントループでの例外の処理方法をカスタマイズできます。
- loop.set_exception_handler(handler)
handler を新しいイベントループ例外ハンドラーとして設定します。
handler が
None
の場合、デフォルトの例外ハンドラーが設定されます。 それ以外の場合、ハンドラーは、(loop, context)
と一致する署名を持つ呼び出し可能である必要があります。ここで、loop
はアクティブなイベントループへの参照であり、context
は[例外の詳細を含むX162X] オブジェクト(コンテキストの詳細については、 call_exception_handler()のドキュメントを参照してください)。
- loop.get_exception_handler()
現在の例外ハンドラーを返します。カスタム例外ハンドラーが設定されていない場合は
None
を返します。バージョン3.5.2の新機能。
- loop.default_exception_handler(context)
デフォルトの例外ハンドラ。
これは、例外が発生し、例外ハンドラーが設定されていない場合に呼び出されます。 これは、デフォルトのハンドラーの動作を延期したいカスタム例外ハンドラーによって呼び出すことができます。
context パラメーターは、 call_exception_handler()と同じ意味です。
- loop.call_exception_handler(context)
現在のイベントループ例外ハンドラーを呼び出します。
context は、次のキーを含む
dict
オブジェクトです(新しいキーは将来のPythonバージョンで導入される可能性があります)。'メッセージ':エラーメッセージ;
'exception'(オプション):例外オブジェクト。
'future'(オプション): asyncio.Future インスタンス;
'handle'(オプション): asyncio.Handle インスタンス;
'protocol'(オプション): Protocol インスタンス;
'transport'(オプション): Transport インスタンス;
'socket'(オプション): socket.socket インスタンス。
ノート
このメソッドは、サブクラス化されたイベントループでオーバーロードしないでください。 カスタム例外処理には、 set_exception_handler()メソッドを使用します。
デバッグモードの有効化
- loop.get_debug()
イベントループのデバッグモード( bool )を取得します。
環境変数 PYTHONASYNCIODEBUG が空でない文字列に設定されている場合、デフォルト値は
True
であり、それ以外の場合はFalse
です。
- loop.set_debug(enabled: bool)
イベントループのデバッグモードを設定します。
バージョン3.7で変更:新しい Python開発モードを使用してデバッグモードを有効にすることもできるようになりました。
サブプロセスの実行
このサブセクションで説明するメソッドは低レベルです。 通常のasync / awaitコードでは、代わりに高レベルのasyncio.create_subprocess_shell()
およびasyncio.create_subprocess_exec()
コンビニエンス関数の使用を検討してください。
ノート
シェルインジェクションの脆弱性を回避するために、すべての空白文字と特殊文字が適切に引用されていることを確認するのはアプリケーションの責任です。 shlex.quote()関数を使用すると、シェルコマンドの作成に使用される文字列内の空白や特殊文字を適切にエスケープできます。
コールバックハンドル
- class asyncio.Handle
loop.call_soon()、 loop.call_soon_threadsafe()によって返されるコールバックラッパーオブジェクト。
- cancel()
コールバックをキャンセルします。 コールバックがすでにキャンセルまたは実行されている場合、このメソッドは効果がありません。
- cancelled()
コールバックがキャンセルされた場合は、
True
を返します。バージョン3.7の新機能。
- class asyncio.TimerHandle
loop.call_later()および loop.call_at()によって返されるコールバックラッパーオブジェクト。
このクラスは、 Handle のサブクラスです。
- when()
スケジュールされたコールバック時間を float 秒として返します。
時間は絶対タイムスタンプであり、 loop.time()と同じ時間参照を使用します。
バージョン3.7の新機能。
サーバーオブジェクト
サーバーオブジェクトは、loop.create_server()
、loop.create_unix_server()
、start_server()
、およびstart_unix_server()
関数によって作成されます。
クラスを直接インスタンス化しないでください。
- class asyncio.Server
Server オブジェクトは非同期コンテキストマネージャーです。
async with
ステートメントで使用すると、async with
ステートメントが完了すると、サーバーオブジェクトが閉じられ、新しい接続を受け入れないことが保証されます。バージョン3.7で変更:サーバーオブジェクトはPython3.7以降の非同期コンテキストマネージャーです。
- close()
提供を停止する:リスニングソケットを閉じ、 sockets 属性を
None
に設定します。既存の着信クライアント接続を表すソケットは開いたままになります。
サーバーは非同期で閉じられます。
wait_closed()
コルーチンを使用して、サーバーが閉じられるまで待機します。
- get_loop()
サーバーオブジェクトに関連付けられたイベントループを返します。
バージョン3.7の新機能。
- is_serving()
サーバーが新しい接続を受け入れている場合は、
True
を返します。バージョン3.7の新機能。
- sockets
サーバーがリッスンしている socket.socket オブジェクトのリスト。
バージョン3.7で変更: Python3.7より前
Server.sockets
は、サーバーソケットの内部リストを直接返すために使用されていました。 3.7では、そのリストのコピーが返されます。
イベントループの実装
asyncioには、 SelectorEventLoop と ProactorEventLoop の2つの異なるイベントループ実装が付属しています。
デフォルトでは、asyncioはUnixでは SelectorEventLoop を使用し、Windowsでは ProactorEventLoop を使用するように構成されています。
- class asyncio.SelectorEventLoop
セレクターモジュールに基づくイベントループ。
特定のプラットフォームで利用可能な最も効率的なセレクターを使用します。 使用する正確なセレクター実装を手動で構成することもできます。
- class asyncio.ProactorEventLoop
「I / O完了ポート」(IOCP)を使用するWindowsのイベントループ。
も参照してください
- class asyncio.AbstractEventLoop
非同期準拠のイベントループの抽象基本クラス。
イベントループメソッドセクションには、
AbstractEventLoop
の代替実装で定義する必要のあるすべてのメソッドが一覧表示されます。
例
このセクションのすべての例意図的には、 loop.run_forever()や loop.call_soon()などの低レベルのイベントループAPIの使用方法を示していることに注意してください。 ]。 最新の非同期アプリケーションをこのように作成する必要はめったにありません。 asyncio.run()のような高レベルの関数の使用を検討してください。
call_soon()を使用したHello World
loop.call_soon()メソッドを使用してコールバックをスケジュールする例。 コールバックは"Hello World"
を表示してから、イベントループを停止します。
call_later()で現在の日付を表示する
現在の日付を毎秒表示するコールバックの例。 コールバックは、 loop.call_later()メソッドを使用して、5秒後に自身を再スケジュールし、イベントループを停止します。
SIGINTおよびSIGTERMのシグナルハンドラーを設定します
(このsignals
の例はUnixでのみ機能します。)
loop.add_signal_handler()メソッドを使用して、シグナルSIGINT
およびSIGTERM
のハンドラーを登録します。