拡張

asyncio を拡張する主な方法は、独自の イベントループ クラスを書くことです。 asyncio には、この作業を簡単にするための補助機能があります。

注釈

サードパーティーが既存の asyncio コードを再利用する際は注意してください。 新しい Python バージョンでは、API の 内部的な 部分について後方互換性が失われる可能性があります。

独自のイベントループを書く

asyncio.AbstractEventLoop には非常に多くのメソッドが宣言されており、すべてを一から実装するのは大変な作業です。

asyncio.BaseEventLoop を継承すれば、多くの共通メソッドの実装をそのまま利用できます。

その代わり、サブクラスでは asyncio.BaseEventLoop に宣言されているものの実装されていない 非公開 メソッドを実装する必要があります。

例えば loop.create_connection() は、引数の検査と DNS によるアドレス解決を行い、サブクラスで実装すべき loop._make_socket_transport() を呼び出します。 _make_socket_transport() は文書化されておらず、内部 API とみなされます。

Future と Task の非公開コンストラクター

asyncio.Future と asyncio.Task は直接作成しないでください。 代わりに、それぞれに対応するファクトリー loop.create_future() と loop.create_task()、または asyncio.create_task() を使ってください。

ただし、サードパーティーの イベントループ は、複雑で高度に最適化されたコードを自前で実装せずに利用するために、組み込みの Future と Task の実装を 再利用 してもかまいません。

この目的のために、以下の 非公開 コンストラクターを紹介します。

Future.__init__(*, loop=None)

組み込みの Future インスタンスを作成します。

loop は省略可能なイベントループのインスタンスです。

Task.__init__(coro, *, loop=None, name=None, context=None)

組み込みの Task インスタンスを作成します。

loop は省略可能なイベントループのインスタンスです。 他の引数については loop.create_task() を参照してください。

バージョン 3.11 で変更: context 引数が追加されました。

タスクの生存期間の管理

サードパーティーのタスク実装では、asyncio.all_tasks() と asyncio.current_task() でタスクを取得できるように、次の関数を呼び出す必要があります。

asyncio._register_task(task)

新しい task を asyncio が管理するタスクとして登録します。

タスクのコンストラクターから呼び出してください。

asyncio._unregister_task(task)

asyncio の内部データ構造から task の登録を解除します。

タスクが終了する直前に呼び出してください。

asyncio._enter_task(loop, task)

現在のタスクを、引数 task に切り替えます。

タスク内の コルーチン を部分的に実行する直前 (coroutine.send() または coroutine.throw() の呼び出し直前) に呼び出してください。

asyncio._leave_task(loop, task)

現在のタスクを task から None に戻します。

coroutine.send() または coroutine.throw() の実行直後に呼び出してください。