ポリシー¶
An event loop policy is a global object used to get and set the current event loop, as well as create new event loops. The default policy can be replaced with built-in alternatives to use different event loop implementations, or substituted by a custom policy that can override these behaviors.
The policy object gets and sets a separate event loop per context. This is per-thread by default, though custom policies could define context differently.
Custom event loop policies can control the behavior of
get_event_loop()
, set_event_loop()
, and new_event_loop()
.
ポリシーオブジェクトは AbstractEventLoopPolicy
抽象基底クラスで定義された API を実装しなければなりません。
ポリシーの取得と設定¶
以下の関数は現在のプロセスに対するポリシーの取得や設定をするために使われます:
- asyncio.get_event_loop_policy()¶
プロセス全体にわたる現在のポリシーを返します。
- asyncio.set_event_loop_policy(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¶
デフォルトの asyncio ポリシーです。Unix では
SelectorEventLoop
、Windows ではProactorEventLoop
を使います。デフォルトのポリシーを手動でインストールする必要はありません。 asyncio はデフォルトポリシーを使うように自動的に構成されます。
バージョン 3.8 で変更: Windows では
ProactorEventLoop
がデフォルトで使われるようになりました。注釈
In Python versions 3.10.9, 3.11.1 and 3.12 the
get_event_loop()
method of the default asyncio policy emits aDeprecationWarning
if there is no running event loop and no current loop is set. In some future Python release this will become an error.
- class asyncio.WindowsSelectorEventLoopPolicy¶
SelectorEventLoop
イベントループ実装を使った別のイベントループポリシーです。利用可能な環境: Windows 。
- class asyncio.WindowsProactorEventLoopPolicy¶
ProactorEventLoop
イベントループ実装を使った別のイベントループポリシーです。利用可能な環境: Windows 。
プロセスのウオッチャー¶
プロセスのウオッチャーは Unix 上でイベントループが子プロセスを監視する方法をカスタマイズすることを可能にします。特に、子プロセスがいつ終了したかをイベントループは知る必要があります。
asyncio では、子プロセスは create_subprocess_exec()
や loop.subprocess_exec()
関数により生成されます。
asyncio は、子プロセスのウオッチャーが実装すべき AbstractChildWatcher
抽象基底クラスを定義しており、さらに異なる4つの実装クラスを提供しています: ThreadedChildWatcher
(デフォルトでこのクラスが使われるように構成されます), MultiLoopChildWatcher
, SafeChildWatcher
, そして FastChildWatcher
です。
サブプロセスとスレッド 節も参照してください。
以下の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)¶
新しい子プロセスのハンドラを登録します。
プロセス ID (PID) が pid であるプロセスが終了した時に
callback(pid, returncode, *args)
コールバック関数が呼び出されるように手配します。同じプロセスに対して別のコールバックを登録した場合、以前登録したハンドラを置き換えます。callback はスレッドセーフな呼び出し可能オブジェクトでなければなりません。
- remove_child_handler(pid)¶
プロセス ID (PID) が pid であるプロセスに対して登録されたハンドラを削除します。
ハンドラが正しく削除された場合
True
を返します。削除するハンドラがない場合はFalse
を返します。
- attach_loop(loop)¶
ウオッチャーをイベントループに接続します。
ウオッチャーがイベントループに接続されている場合、新しいイベントループに接続される前に接続済みのイベントループから切り離されます。
注: 引数は
None
をとることができます。
- is_active()¶
ウオッチャーが利用可能な状態なら
True
を返します。現在の子プロセスのウオッチャーが アクティブでない 場合にサブプロセスを生成すると
RuntimeError
例外が送出されます。バージョン 3.8 で追加.
- close()¶
ウオッチャーをクローズします。
このメソッドは、ウオッチャーの背後にあるリソースを確実にクリーンアップするために必ず呼び出さなければなりません。
- class asyncio.ThreadedChildWatcher¶
この実装は、各サブプロセスの生成時に新しい待ち受けスレッドを開始します。
このクラスは asyncio イベントループがメインでない OS スレッド上で実行されていても期待通りに動きます。
There is no noticeable overhead when handling a big number of children (O(1) each time a child terminates), but starting a thread per process requires extra memory.
このウオッチャーはデフォルトで使われます。
バージョン 3.8 で追加.
- class asyncio.MultiLoopChildWatcher¶
この実装はインスタンス化の際に
SIGCHLD
シグナルハンドラを登録します。これにより、独自のSIGCHLD
シグナルハンドラをインストールするようなサードパーティのコードを壊す可能性があります。このウオッチャーは、各プロセスに明示的に
SIGCHLD
シグナルをポーリングさせることにより、プロセスを生成する他のコードを中断させないようにします。いったんウオッチャーがインストールされると、異なるスレッドからのサブプロセスの実行について特に制限はありません。
The solution is safe but it has a significant overhead when handling a big number of processes (O(n) each time a
SIGCHLD
is received).バージョン 3.8 で追加.
- class asyncio.SafeChildWatcher¶
この実装はメインスレッドでアクティブなイベントループを使って
SIGCHLD
シグナルを処理します。メインスレッドでイベントループが実行中でない場合、別のスレッドからサブプロセスを生成することはできません (RuntimeError
例外が送出されます)。このウオッチャーは、各プロセスに明示的に
SIGCHLD
シグナルをポーリングさせることにより、プロセスを生成する他のコードを中断させないようにします。This solution is as safe as
MultiLoopChildWatcher
and has the same O(n) complexity but requires a running event loop in the main thread to work.
- class asyncio.FastChildWatcher¶
この実装は終了した子プロセスを得るために直接
os.waitpid(-1)
を呼び出します。これにより、プロセスを生成してその終了を待ち受ける別のコードを壊す可能性があります。There is no noticeable overhead when handling a big number of children (O(1) each time a child terminates).
このソリューションは、
SafeChildWatcher
と同様にメインスレッドで実行中のイベントループが必要です。
- class asyncio.PidfdChildWatcher¶
この実装は子プロセスの終了を待ち受けるためにプロセスのファイル記述子 (pidfds) をポーリングします。いくつかの点で、
PidfdChildWatcher
は "Goldilocks" 的な子プロセスのウオッチャー実装です。この実装はシグナルもスレッドも必要とせず、イベントループの外で生成されたいかなるプロセスとも干渉せず、しかもイベントループから生成されたサブプロセスの数に対して線形にスケールします。主な欠点は pidfds が Linux 特有であり、最近のカーネル (5.3+) でしか動かないことです。バージョン 3.9 で追加.
ポリシーのカスタマイズ¶
新しいイベントループのポリシーを実装するためには、以下に示すように 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())