ポリシー
イベントループポリシーは、イベントループの管理を制御するグローバルなプロセスごとのオブジェクトです。 各イベントループにはデフォルトのポリシーがあり、ポリシーAPIを使用して変更およびカスタマイズできます。
ポリシーは、 context の概念を定義し、コンテキストごとに個別のイベントループを管理します。 デフォルトのポリシーでは、 context が現在のスレッドであると定義されています。
カスタムイベントループポリシーを使用することにより、 get_event_loop()、 set_event_loop()、および new_event_loop()関数の動作をカスタマイズできます。
ポリシーオブジェクトは、 AbstractEventLoopPolicy 抽象基本クラスで定義されたAPIを実装する必要があります。
ポリシーの取得と設定
次の関数を使用して、現在のプロセスのポリシーを取得および設定できます。
- asyncio.get_event_loop_policy()
- 現在のプロセス全体のポリシーを返します。
- asyncio.set_event_loop_policy(policy)
現在のプロセス全体のポリシーをポリシーに設定します。
policy が
None
に設定されている場合、デフォルトのポリシーが復元されます。
ポリシーオブジェクト
抽象イベントループポリシーの基本クラスは、次のように定義されています。
- class asyncio.AbstractEventLoopPolicy
asyncioポリシーの抽象基本クラス。
- get_event_loop()
現在のコンテキストのイベントループを取得します。
AbstractEventLoop インターフェイスを実装するイベントループオブジェクトを返します。
このメソッドは
None
を返すことはありません。バージョン3.6で変更されました。
- set_event_loop(loop)
現在のコンテキストのイベントループを loop に設定します。
- new_event_loop()
新しいイベントループオブジェクトを作成して返します。
このメソッドは
None
を返すことはありません。
- get_child_watcher()
子プロセスウォッチャーオブジェクトを取得します。
AbstractChildWatcher インターフェイスを実装するウォッチャーオブジェクトを返します。
この関数はUnix固有です。
- set_child_watcher(watcher)
現在の子プロセスウォッチャーを watcher に設定します。
この関数はUnix固有です。
asyncioには、次の組み込みポリシーが付属しています。
- class asyncio.DefaultEventLoopPolicy
デフォルトの非同期ポリシー。 UnixプラットフォームとWindowsプラットフォームの両方で SelectorEventLoop を使用します。
デフォルトのポリシーを手動でインストールする必要はありません。 asyncioは、デフォルトのポリシーを自動的に使用するように構成されています。
- class asyncio.WindowsProactorEventLoopPolicy
- ProactorEventLoop イベントループ実装を使用する代替イベントループポリシー。
プロセスウォッチャー
プロセスウォッチャーを使用すると、イベントループがUnix上の子プロセスを監視する方法をカスタマイズできます。 具体的には、イベントループは、子プロセスがいつ終了したかを知る必要があります。
asyncioでは、子プロセスはcreate_subprocess_exec()
およびloop.subprocess_exec()
関数で作成されます。
asyncioは、子ウォッチャーが実装する必要がある AbstractChildWatcher 抽象基本クラスを定義し、 SafeChildWatcher (デフォルトで使用されるように構成)と FastChildWatcher の2つの異なる実装があります。
サブプロセスとスレッドセクションも参照してください。
次の2つの関数を使用して、asyncioイベントループで使用される子プロセスウォッチャーの実装をカスタマイズできます。
- asyncio.get_child_watcher()
- 現在のポリシーの現在の子ウォッチャーを返します。
- asyncio.set_child_watcher(watcher)
- 現在のポリシーでは、現在の子ウォッチャーを watcher に設定します。 watcher は、 AbstractChildWatcher 基本クラスで定義されたメソッドを実装する必要があります。
ノート
サードパーティのイベントループの実装は、カスタムの子ウォッチャーをサポートしていない可能性があります。 このようなイベントループの場合、 set_child_watcher()の使用は禁止されているか、効果がない可能性があります。
- class asyncio.AbstractChildWatcher
- add_child_handler(pid, callback, \*args)
新しい子ハンドラーを登録します。
pid に等しいPIDのプロセスが終了したときに
callback(pid, returncode, *args)
が呼び出されるように調整します。 同じプロセスに別のコールバックを指定すると、前のハンドラーが置き換えられます。コールバック呼び出し可能オブジェクトはスレッドセーフである必要があります。
- remove_child_handler(pid)
pid に等しいPIDを持つプロセスのハンドラーを削除します。
この関数は、ハンドラーが正常に削除された場合は
True
を返し、削除するものがない場合はFalse
を返します。
- attach_loop(loop)
ウォッチャーをイベントループに接続します。
ウォッチャーが以前にイベントループに接続されていた場合は、新しいループに接続する前に、まずウォッチャーが切り離されます。
注:ループは
None
の場合があります。
- close()
ウォッチャーを閉じます。
基になるリソースが確実にクリーンアップされるようにするには、このメソッドを呼び出す必要があります。
- class asyncio.SafeChildWatcher
この実装は、
SIGCHLD
信号ですべてのプロセスを明示的にポーリングすることにより、他のコード生成プロセスの中断を回避します。これは安全なソリューションですが、多数のプロセスを処理する場合(
SIGCHLD
を受信するたびに O(n))、かなりのオーバーヘッドが発生します。asyncioは、デフォルトでこの安全な実装を使用します。
- class asyncio.FastChildWatcher
この実装は、
os.waitpid(-1)
を直接呼び出して、終了したすべてのプロセスを取得します。他のコード生成プロセスを中断し、それらの終了を待機する可能性があります。多数の子を処理する場合、目立ったオーバーヘッドはありません(子が終了するたびに O(1))。
カスタムポリシー
新しいイベントループポリシーを実装するには、 DefaultEventLoopPolicy をサブクラス化し、カスタム動作が必要なメソッドをオーバーライドすることをお勧めします。例:
class MyEventLoopPolicy(asyncio.DefaultEventLoopPolicy):
def get_event_loop(self):
"""Get the event loop.
This may be None or an instance of EventLoop.
"""
loop = super().get_event_loop()
# Do something with loop ...
return loop
asyncio.set_event_loop_policy(MyEventLoopPolicy())