イベントループ

ソースコード: Lib/asyncio/events.py, Lib/asyncio/base_events.py


まえがき

イベントループは全ての asyncio アプリケーションの中核をなす存在です。イベントループは非同期タスクやコールバックを実行し、ネットワーク I/O を処理し、サブプロセスを実行します。

アプリケーション開発者は通常 asyncio.run() のような高水準の ayncio 関数だけを利用し、ループオブジェクトを参照したり、ループオブジェクトのメソッドを呼び出したりすることはほとんどありません。この節は、イベントループの振る舞いに対して細かい調整が必要な、低水準のコード、ライブラリ、フレームワークの開発者向けです。

イベントループの取得

以下の低水準関数はイベントループの取得、設定、生成するために使います:

asyncio.get_running_loop()

現在の OS スレッドで実行中のイベントループを取得します。

実行中のイベントループがなければ RuntimeError を送出します。

この関数は、コルーチンまたはコールバックからのみ呼び出せます。

Added in version 3.7.

asyncio.get_event_loop()

現在のイベントループを取得します。

コルーチンまたはコールバック (call_soon() などの API でスケジュールしたもの) から呼び出すと、常に実行中のイベントループを返します。

実行中のイベントループがなければ、get_event_loop_policy().get_event_loop() の呼び出し結果を返します。

この関数の振る舞いは (特にイベントループポリシーをカスタマイズした場合) 複雑なため、コルーチンやコールバックでは get_event_loop() よりも get_running_loop() を使うほうが好ましいと考えられます。

前述のとおり、これらの低水準関数でイベントループを手動で作成・クローズする代わりに、より高水準な asyncio.run() の使用を検討してください。

バージョン 3.14 で変更: 現在のイベントループがなければ RuntimeError を送出するようになりました。

注釈

asyncio のポリシーシステムは非推奨で、Python 3.16 で削除されます。 それ以降、この関数は実行中のイベントループがあればそれを返し、なければ set_event_loop() で設定したループを返します。

asyncio.set_event_loop(loop)

loop を OS スレッドの現在のイベントループに設定します。

asyncio.new_event_loop()

新しいイベントループオブジェクトを生成して返します。

get_event_loop(), set_event_loop(), および new_event_loop() 関数の振る舞いは、 カスタムイベントループポリシーを設定する ことにより変更することができます。

内容

このページは以下の節から構成されます:

イベントループのメソッド

イベントループは以下の 低水準な API を持っています:

ループの開始と停止

loop.run_until_complete(future)

future (Future のインスタンス) が完了するまで実行します。

引数が コルーチンオブジェクト の場合、暗黙のうちに asyncio.Task として実行されるようにスケジュールされます。

Future の結果を返すか、例外を送出します。

loop.run_forever()

stop() が呼び出されるまでイベントループを実行します。

run_forever() メソッドが呼ばれるより前に stop() メソッドが呼ばれた場合、イベントループはタイムアウトをゼロにして一度だけ I/O セレクタの問い合わせ処理を行い、 I/O イベントに対してスケジュールされた全てのコールバック (および既にスケジュール済みのコールバック) を実行したのち、終了します。

run_forever() メソッドを実行中に stop() メソッドが呼び出された場合、イベントループは現在処理されているすべてのコールバックを実行してから終了します。 この場合、コールバックにより新たにスケジュールされるコールバックは実行されないことに注意してください; これら新たにスケジュールされたコールバックは、次に run_forever() または run_until_complete() が呼び出されたときに実行されます。

loop.stop()

イベントループを停止します。

loop.is_running()

イベントループが現在実行中の場合 True を返します。

loop.is_closed()

イベントループが閉じられていた場合 True を返します。

loop.close()

イベントループをクローズします。

この関数が呼び出される時点で、イベントループが実行中であってはいけません。保留中のコールバックはすべて破棄されます。

このメソッドは全てのキューをクリアし、エグゼキューターが実行完了するのを待たずにシャットダウンします。

このメソッドはべき等 (何回実行しても結果は同じ) であり取り消せません。イベントループがクローズされた後、他のいかなるメソッドも呼び出すべきではありません。

async loop.shutdown_asyncgens()

現在オープンになっているすべての asynchronous generator (非同期ジェネレータ) オブジェクトをスケジュールし、 aclose() メソッドを呼び出すことでそれらをクローズします。 このメソッドの呼び出し後に新しい非同期ジェネレータがイテレートされると、イベントループは警告を発します。このメソッドはスケジュールされたすべての非同期ジェネレータの終了処理を確実に行うために使用すべきです。

asyncio.run() を使った場合はこの関数を呼び出す必要はありません。

以下はプログラム例です:

try:
    loop.run_forever()
finally:
    loop.run_until_complete(loop.shutdown_asyncgens())
    loop.close()

Added in version 3.6.

async loop.shutdown_default_executor(timeout=None)

デフォルトの Executor の終了をスケジュールし、ThreadPoolExecutor のすべてのスレッドの終了を待ちます。 このメソッドを呼び出した後で loop.run_in_executor() によりデフォルトの Executor を使うと、RuntimeError が送出されます。

timeout は、Executor のスレッドの終了を待つ制限時間を秒単位の float で指定します。 デフォルトの None では、待ち時間に制限はありません。

timeout に達すると RuntimeWarning を出し、スレッドの終了を待たずにデフォルトの Executor の終了処理を行います。

注釈

asyncio.run() はデフォルトの Executor の終了処理を自動的に行うため、これを使う場合はこのメソッドを呼び出さないでください。

Added in version 3.9.

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

コールバックのスケジューリング

loop.call_soon(callback, *args, context=None)

イベントループの次のイテレーションで callback に指定したコールバック (callback) を args 引数で呼び出すようにスケジュールします。

asyncio.Handle のインスタンスを返します。このインスタンスを使ってスケジュールしたコールバックをキャンセルすることができます。

コールバックは登録された順に呼び出されます。各コールバックは厳密に1回だけ呼び出されます。

省略可能なキーワード専用引数 context には、callback の実行に使う contextvars.Context を指定します。 context を指定しなければ、現在のコンテキストを使います。

call_soon_threadsafe() とは異なり、このメソッドはスレッドセーフではありません。

loop.call_soon_threadsafe(callback, *args, context=None)

call_soon() のスレッドセーフな版です。 call_soon() はスレッドセーフではないため、別のスレッドからコールバックをスケジュールする場合は 必ず この関数を使ってください。

この関数は、再入可能なコンテキストやシグナルハンドラーから安全に呼び出せます。 ただし、そのようなコンテキストで返されたハンドルを使うことは、安全でも有用でもありません。

すでにクローズされたイベントループに対してこのメソッドが呼び出された場合 RuntimeError 例外を送出します。これはメインアプリケーションが終了しているにもかかわらずセカンダリスレッドでメソッドが呼び出されるといった場合に起こりえます。

このドキュメントの 並行処理とマルチスレッド処理 節を参照してください。

バージョン 3.7 で変更: キーワード引数 context が追加されました。詳細は PEP 567 を参照してください。

注釈

ほとんどの asyncio モジュールのスケジューリング関数は、キーワード引数をコールバックに渡すことを許していません。キーワード引数を渡すためには functools.partial() を使ってください:

# print("Hello", flush=True) をスケジュールする
loop.call_soon(
    functools.partial(print, "Hello", flush=True))

asyncio は partial オブジェクトのデバッグメッセージやエラーメッセージをよりよく可視化することができるため、通常はラムダ式よりも partial オブジェクトを使う方が便利です。

遅延コールバックのスケジューリング

イベントループは、コールバック関数を未来のある時点で呼び出されるようにスケジュールする仕組みを提供します。イベントループは時刻が戻らない単調な時計 (monotonic clock) を使って時刻を追跡します。

loop.call_later(delay, callback, *args, context=None)

delay 秒経過後にコールバック関数 callback を呼び出すようにスケジュールします。 delay には整数または浮動小数点数を指定します。

asyncio.TimerHandle のインスタンスを返します。このインスタンスを使ってスケジュールしたコールバックをキャンセルすることができます。

callback は厳密に一度だけ呼び出されます。2つのコールバックが完全に同じ時間にスケジュールされた場合、呼び出しの順序は未定義です。

省略可能な位置引数 args は、コールバックの呼び出し時に渡されます。 callback に キーワード引数を渡す には、functools.partial() を使ってください。

オプションのキーワード引数 context を使って、コールバック*callback* を実行する際のコンテキスト contextvars.Context を設定することができます。コンテキスト context が指定されない場合は現在のコンテキストが使われます。

注釈

性能上の理由から、loop.call_later() でスケジュールしたコールバックは、時計の分解能の 1 単位分だけ早く実行される可能性があります (time.get_clock_info('monotonic').resolution を参照)。

バージョン 3.7 で変更: キーワード引数 context が追加されました。詳細は PEP 567 を参照してください。

バージョン 3.8 で変更: Python 3.7 またはそれ以前のバージョンでは、デフォルトイベントループの実装を利用した場合に遅延時間 delay が1日を超えることができませんでした。この問題は Python 3.8 で修正されました。

loop.call_at(when, callback, *args, context=None)

絶対値の時刻 when (整数または浮動小数点数) にコールバックを呼び出すようにスケジュールします。 loop.time() と同じ参照時刻を使用します。

このメソッドの振る舞いは call_later() と同じです。

asyncio.TimerHandle のインスタンスを返します。このインスタンスを使ってスケジュールしたコールバックをキャンセルすることができます。

注釈

性能上の理由から、loop.call_at() でスケジュールしたコールバックは、時計の分解能の 1 単位分だけ早く実行される可能性があります (time.get_clock_info('monotonic').resolution を参照)。

バージョン 3.7 で変更: キーワード引数 context が追加されました。詳細は PEP 567 を参照してください。

バージョン 3.8 で変更: Python 3.7 またはそれ以前のバージョンでは、デフォルトイベントループの実装を利用した場合に現在の時刻と when との差が1日を超えることができませんでした。この問題は Python 3.8 で修正されました。

loop.time()

現在の時刻を float 値で返します。時刻はイベントループが内部で参照している時刻が戻らない単調な時計 (monotonic clock) に従います。

注釈

バージョン 3.8 で変更: Python 3.7 またはそれ以前のバージョンでは、タイムアウト (相対値 delay もしくは絶対値 when) は1日を超えることができませんでした。この問題は Python 3.8 で修正されました。

参考

関数 asyncio.sleep()。

Future とタスクの作成

loop.create_future()

イベントループに接続した asyncio.Future オブジェクトを生成します。

asyncio でフューチャーオブジェクトを作成するために推奨される方法です。このメソッドにより、サードパーティ製のイベントループがFutures クラスの(パフォーマンスや計測方法が優れた) 代替実装を提供することを可能にします。

Added in version 3.5.2.

loop.create_task(coro, *, name=None, context=None, eager_start=None, **kwargs)

コルーチン coro の実行をスケジュールします。 Task オブジェクトを返します。

サードパーティのイベントループは相互運用のための自身の Task のサブクラスを使用できます。この場合、結果は Task のサブクラスになります。

関数のシグネチャ全体は Task のコンストラクター (またはファクトリー) とほぼ同じで、この関数に渡したキーワード引数はすべて、その呼び出し先に渡されます。

name 引数が指定され、値が None でない場合、 Task.set_name() メソッドにより name がタスクの名前として設定されます。

省略可能なキーワード引数 context によって、coro を実行するためのカスタムの contextvars.Context を指定できます。context が省略された場合、現在のコンテキストのコピーが作成されます。

省略可能なキーワード専用引数 eager_start は、create_task() の呼び出し中にタスクの実行を即座に開始するか、後で実行するようスケジュールするかを指定します。 eager_start を渡さなければ、loop.set_task_factory() で設定したモードが使われます。

バージョン 3.8 で変更: name パラメータを追加しました。

バージョン 3.11 で変更: context パラメータを追加しました。

バージョン 3.13.3 で変更: name と context を含む任意の追加パラメーターを渡す kwargs が追加されました。

バージョン 3.13.4 で変更: name と、値が None の場合の context を渡す変更を取り消しました。 それ以外の任意のキーワード引数は、3.13.3 との後方互換性を保つため、引き続き渡されます。

バージョン 3.14 で変更: すべての kwargs を渡すようになりました。 eager_start パラメーターは、タスクを即座に実行するファクトリーで機能します。

loop.set_task_factory(factory)

loop.create_task() が使用するタスクファクトリーを設定します。

factory が None の場合は、デフォルトのタスクファクトリーを設定します。 それ以外の場合、factory はシグネチャが (loop, coro, **kwargs) に対応する 呼び出し可能オブジェクト でなければなりません。 ここで loop は使用するイベントループへの参照、coro はコルーチンオブジェクトです。 この呼び出し可能オブジェクトは、すべての kwargs を呼び出し先に渡し、asyncio.Task と互換性のあるオブジェクトを返す必要があります。

バージョン 3.13.3 で変更: すべての kwargs を asyncio.Task に渡すことが必須になりました。

バージョン 3.13.4 で変更: name をタスクファクトリーに渡さなくなりました。 context も、値が None の場合は渡さなくなりました。

バージョン 3.14 で変更: name と context を、再び無条件にタスクファクトリーに渡すようになりました。

loop.get_task_factory()

タスクファクトリを返します。デフォルトのタスクファクトリを使用中の場合は None を返します。

ネットワーク接続の確立

async loop.create_connection(protocol_factory, host=None, port=None, *, ssl=None, family=0, proto=0, flags=0, sock=None, local_addr=None, server_hostname=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None, happy_eyeballs_delay=None, interleave=None, all_errors=False)

host と port で指定されたアドレスとのストリーミングトランスポート接続をオープンします。

ソケットファミリーは host (または family 引数が与えられた場合は family) に依存し、 AF_INET か AF_INET6 のいずれかを指定します。

ソケットタイプは SOCK_STREAM になります。

protocol_factory は asyncio プロトコル の実装を返す呼び出し可能オブジェクトでなければなりません。

このメソッドはバックグラウンドで接続の確立を試みます。成功した場合、メソッドは (transport, protocol) のペアを返します。

時系列での下層処理の概要は以下のとおりです:

  1. 接続を確立し、その接続に対する トランスポート が生成されます。

  2. protocol_factory が引数なしで呼び出され、ファクトリが プロトコル インスタンスを返すよう要求します。

  3. プロトコルインスタンスが connection_made() メソッドを呼び出すことにより、トランスポートと紐付けられます。

  4. 成功すると (transport, protocol) タプルが返されます。

作成されたトランスポートは実装依存の双方向ストリームです。

その他の引数:

  • ssl: 偽値以外が与えられた場合、SSL/TLS トランスポートが作成されます (デフォルトでは暗号化なしの TCP トランスポートが作成されます)。 ssl が ssl.SSLContext オブジェクトの場合、このコンテキストがトランスポートを作成するために使用されます; ssl が True の場合、 ssl.create_default_context() が返すデフォルトのコンテキストが使われます。

  • server_hostname は対象サーバーの証明書との一致を確認するためのホスト名を設定または上書きします。この引数は ssl が None でない場合のみ設定すべきです。デフォルトでは host に指定したサーバー名が使用されます。 host が空の文字列の場合のデフォルト値は設定されていません。その場合、 server_hostname を必ず指定してください。 server_hostname も空の文字列の場合は、ホスト名の一致確認は行われません (これは深刻なセキュリティリスクであり、中間者攻撃を受ける可能性があります)。

  • family、proto、flags は省略可能な引数で、それぞれアドレスファミリー、プロトコル、フラグを指定します。 host の名前解決のために getaddrinfo() に渡されます。 指定する場合は、socket モジュールの対応する整数定数を使ってください。

  • happy_eyeballs_delay が設定されると、この接続に対して Happy Eyeballs が有効化されます。設定する値は浮動小数点数であり、次の接続試行を開始する前に、現在の接続試行が完了するのを待つ時間を秒単位で表現します。この値は RFC 8305 で定義されている "接続試行遅延" に相当します。RFC で推奨されている実用的なデフォルト値は 0.25 (250 ミリ秒) です。

  • interleave はホスト名が複数の IP アドレスに名前解決される場合のアドレスの並べ替えを制御します。 0 または未指定の場合並べ替えは行われず、 getaddrinfo() が返す順番にしたがってアドレスへの接続を試行します。正の整数が指定されると、アドレスはアドレスファミリに応じてインターリーブされます。このとき、与えられた整数は RFC 8305 で定義される "最初のアドレスファミリカウント (First Address Family Count)" として解釈されます。デフォルト値は、 happy_eyeballs_delay が指定されない場合は 0 であり、指定された場合は 1 です。

  • sock を与える場合、トランスポートに使用される、既存の、かつ接続済の socket.socket オブジェクトを指定します。sock を指定する場合、host、 port、 family、 proto、 flags、 happy_eyeballs_delay、 interleave および local_addr のいずれも指定してはいけません。

    注釈

    sock 引数を渡すと、ソケットの所有権は作成されたトランスポートに移ります。 ソケットを閉じるには、トランスポートの close() メソッドを呼び出してください。

  • local_addr を与える場合、ソケットをローカルにバインドするために使用する (local_host, local_port) タプルを指定します。 local_host と local_port は、 host および port と同じく getaddrinfo() を使ってルックアップされます。

  • ssl_handshake_timeout は TLS ハンドシェイクが完了するまでの (TLS 接続のための) 待ち時間を秒単位で指定します。指定した待ち時間を超えると接続は中断します。 None が与えられた場合はデフォルト値 60.0 が使われます。

  • ssl_shutdown_timeout は、接続を中断する前に SSL の終了処理を待つ時間を秒単位で指定します。 None (デフォルト) の場合は 30.0 秒です。

  • all_errors は、接続を確立できなかった場合に送出する例外を指定します。 デフォルトでは Exception を一つだけ送出します。 例外が一つだけの場合や、すべてのエラーメッセージが同じ場合は最初の例外、それ以外の場合はエラーメッセージをまとめた一つの OSError です。 all_errors が True の場合、すべての例外を含む ExceptionGroup を送出します (例外が一つだけでも同じです)。

バージョン 3.5 で変更: ProactorEventLoop において SSL/TLS のサポートが追加されました。

バージョン 3.6 で変更: 全ての TCP 接続に対してデフォルトでソケットオプション socket.TCP_NODELAY が設定されるようになりました。

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

バージョン 3.8 で変更: happy_eyeballs_delay と interleave が追加されました。

Happy Eyeballs アルゴリズム: デュアルスタックホストでの接続を成功させる方法。 サーバーへの IPv4 の経路とプロトコルが機能していても、IPv6 の経路とプロトコルが機能していないと、デュアルスタックのクライアントアプリケーションでは、IPv4 専用のクライアントに比べて接続が大幅に遅れることがあります。 デュアルスタックのクライアントで利用者の使い勝手が悪くなるため、これは望ましくありません。 この文書は、利用者に見えるこの遅延を減らすアルゴリズムの要件を定め、一つのアルゴリズムを示します。

詳しくは右記を参照してください: https://datatracker.ietf.org/doc/html/rfc6555

バージョン 3.11 で変更: ssl_shutdown_timeout パラメータが追加されました。

バージョン 3.12 で変更: all_errors が追加されました

バージョン 3.15 で変更: ssl.check_hostname が True で、server_hostname が指定されていない場合に ValueError を送出するようになりました。

参考

open_connection() 関数は高水準の代替 API です。この関数は(StreamReader, StreamWriter) のペアを返し、 async/await コードから直接使うことができます。

async loop.create_datagram_endpoint(protocol_factory, local_addr=None, remote_addr=None, *, family=0, proto=0, flags=0, reuse_port=None, allow_broadcast=None, sock=None)

データグラム接続 (UDP) を生成します。

ソケットファミリーは host (または family 引数が与えられた場合は family) に依存し、 AF_INET、 AF_INET6、AF_UNIX のいずれかを指定します。

ソケットタイプは SOCK_DGRAM になります。

protocol_factory は asyncio プロトコル の実装を返す呼び出し可能オブジェクトでなければなりません。

成功すると (transport, protocol) タプルが返されます。

その他の引数:

  • local_addr が指定される場合、ソケットをローカルにバインドするための (local_host, local_port) のタプルを指定します。 local_host と local_port は getaddrinfo() メソッドを使用して検索されます。

    注釈

    Windows で Proactor イベントループを使い、local_addr=None として実行すると、errno.WSAEINVAL の OSError が送出されます。

  • remote_addr を指定する場合は、ソケットをリモートアドレスに接続するための (remote_host, remote_port) タプルを渡します。 remote_host と remote_port は getaddrinfo() を使って検索されます。

  • family、proto、flags は省略可能な引数で、それぞれアドレスファミリー、プロトコル、フラグを指定します。 host の名前解決のために getaddrinfo() に渡されます。 指定する場合は、socket モジュールの対応する整数定数を使ってください。

  • reuse_port は、同じポートにバインドされた既存の端点すべてがこのフラグを設定して生成されている場合に限り、この端点を既存の端点と同じポートにバインドすることを許可するよう、カーネルに指示します(訳註: ソケットのオプション SO_REUSEPORT を使用します)。このオプションは、Windows やいくつかの UNIX システムではサポートされていません。socket.SO_REUSEPORT 定数が定義されていなければ、この機能はサポートされません。

  • allow_broadcast は、カーネルに、このエンドポイントがブロードキャストアドレスにメッセージを送信することを許可するように指示します。

  • オプションの sock を指定することで、既存の、すでに接続されている socket.socket をトランスポートで使用することができます。このオプションを使用する場合、local_addr と remote_addr は省略してください (None でなければなりません)。

    注釈

    sock 引数を渡すと、ソケットの所有権は作成されたトランスポートに移ります。 ソケットを閉じるには、トランスポートの close() メソッドを呼び出してください。

UDP echo クライアントプロトコル および UDP echo サーバープロトコル の例を参照してください。

バージョン 3.4.4 で変更: family, proto, flags, reuse_address, reuse_port, allow_broadcast, sock パラメータが追加されました。

バージョン 3.8 で変更: Windows サポートが追加されました。

バージョン 3.8.1 で変更: socket.SO_REUSEADDR の利用が UDP に対して重大なセキュリティ上の懸念をもたらすため、 reuse_address パラメータはサポートされなくなりました。明示的に reuse_address=True を設定すると例外を送出します。

SO_REUSEADDR を使って、同一の UDP ソケットアドレスに対して複数のプロセスが異なる UID でソケットを割り当てている場合、受信パケットは複数のソケット間にランダムに分散する可能性があります。

サポートされているプラットフォームでは、 reuse_port が同様の機能に対する代用品として利用できます。 reuse_port は代替機能として socket.SO_REUSEPORT を使っており、複数のプロセスが異なる UID で同一のソケットに対して割り当てられるのを明確に禁止します。

バージョン 3.11 で変更: Python 3.8.1、3.7.6、3.6.10 以降で無効になっていた reuse_address パラメーターが、完全に削除されました。

async loop.create_unix_connection(protocol_factory, path=None, *, ssl=None, sock=None, server_hostname=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None)

Unix 接続を生成します。

ソケットファミリーは AF_UNIX になります; また、ソケットタイプは SOCK_STREAM になります。

成功すると (transport, protocol) タプルが返されます。

path は Unix ドメインソケット名で、 sock パラメータが指定されない場合は必須です。 抽象 Unix ソケット、 str、 bytes、 and Path 形式でのパスがサポートされています。

このメソッドの引数についての詳細は loop.create_connection() メソッドのドキュメントを参照してください。

バージョン 3.7 で変更: ssl_handshake_timeout パラメーターが追加されました。 path パラメーターに path-like object を指定できるようになりました。

バージョン 3.11 で変更: ssl_shutdown_timeout パラメータが追加されました。

ネットワークサーバの生成

async loop.create_server(protocol_factory, host=None, port=None, *, family=socket.AF_UNSPEC, flags=socket.AI_PASSIVE, sock=None, backlog=100, ssl=None, reuse_address=None, reuse_port=None, keep_alive=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None, start_serving=True)

アドレス host のポート port で接続を待ち受ける TCP サーバー (ソケットタイプ SOCK_STREAM) を作成します。

Server オブジェクトを返します。

引数:

  • protocol_factory は asyncio プロトコル の実装を返す呼び出し可能オブジェクトでなければなりません。

  • host パラメータはいくつかの方法で指定することができ、その値によってサーバーがどこをリッスンするかが決まります。

    • host が文字列の場合、 TCP サーバーは host で指定した単一のネットワークインターフェースに束縛されます。

    • host が文字列のシーケンスである場合、 TCP サーバーはそのシーケンスで指定された全てのネットワークインターフェースに束縛されます。

    • host が空の文字列か None の場合、すべてのインターフェースが想定され、複合的なソケットのリスト (通常は一つが IPv4、もう一つが IPv6) が返されます。

  • port パラメーターには、サーバーが待ち受けるポートを指定できます。 0 または None (デフォルト) の場合、未使用のポートがランダムに選ばれます。 host が複数のネットワークインターフェースに解決される場合は、インターフェースごとに異なるランダムなポートが選ばれることに注意してください。

  • family に socket.AF_INET または AF_INET6 を指定すると、ソケットでそれぞれ IPv4 または IPv6 を使うよう強制できます。 指定しなければホスト名から決まり、デフォルト値は AF_UNSPEC です。

  • flags は getaddrinfo() のためのビットマスクになります。

  • サーバーで既存のソケットオブジェクトを使用するために、オプションの引数 sock にソケットオブジェクトを設定することができます。指定した場合、 host と port を指定してはいけません。

    注釈

    sock 引数を渡すと、ソケットの所有権は作成されたサーバーに移ります。 ソケットを閉じるには、サーバーの close() メソッドを呼び出してください。

  • backlog は listen() に渡される、キューに入るコネクションの最大数になります (デフォルトは 100)。

  • 確立した接続の上で TLS を有効化するために、 ssl に SSLContext のインスタンスを指定することができます。

  • reuse_address は、TIME_WAIT 状態にあるローカルソケットを、その状態が自然にタイムアウトするのを待つことなく再利用するようカーネルに指示します(訳註: ソケットのオプション SO_REUSEADDR を使用します)。指定しない場合、UNIX では自動的に True が設定されます。

  • reuse_port は、同じポートにバインドされた既存の端点すべてがこのフラグを設定して生成されている場合に限り、この端点を既存の端点と同じポートにバインドすることを許可するよう、カーネルに指示します(訳註: ソケットのオプション SO_REUSEPORT を使用します)。このオプションは、Windows ではサポートされていません。

  • keep_alive を True にすると、定期的なメッセージ送信を有効にして接続を維持します。

バージョン 3.13 で変更: keep_alive パラメーターが追加されました。

  • ssl_handshake_timeout は TLS ハンドシェイクが完了するまでの (TLS サーバーのための) 待ち時間を秒単位で指定します。指定した待ち時間を超えると接続は中断します。 None が与えられた場合はデフォルト値 60.0 が使われます。

  • ssl_shutdown_timeout は、接続を中断する前に SSL の終了処理を待つ時間を秒単位で指定します。 None (デフォルト) の場合は 30.0 秒です。

  • start_serving が True に設定された場合 (これがデフォルトです)、 生成されたサーバーは即座に接続の受け付けを開始します。 False が指定された場合、ユーザーは接続の受け付けを開始するために Server.start_serving() または Server.serve_forever() を待ち受け (await) る必要があります。

バージョン 3.5 で変更: ProactorEventLoop において SSL/TLS のサポートが追加されました。

バージョン 3.5.1 で変更: host パラメータに文字列のシーケンスを指定できるようになりました。

バージョン 3.6 で変更: ssl_handshake_timeout と start_serving パラメーターが追加されました。 すべての TCP 接続で、デフォルトでソケットオプション socket.TCP_NODELAY を設定するようになりました。

バージョン 3.11 で変更: ssl_shutdown_timeout パラメータが追加されました。

参考

start_server() 関数は高水準の代替 API です。この関数は StreamReader と StreamWriter のペアを返し、async/await コードから使うことができます。

async loop.create_unix_server(protocol_factory, path=None, *, sock=None, backlog=100, ssl=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None, start_serving=True, cleanup_socket=True)

loop.create_server() と似ていますが、ソケットファミリー AF_UNIX を使います。

path は Unix ドメインソケット名で、 sock パラメータが指定されない場合は必須です。 抽象 Unix ソケット、 str、 bytes、 and Path 形式でのパスがサポートされています。

cleanup_socket が真の場合、サーバーを閉じると Unix ソケットをファイルシステムから自動的に削除します。 ただし、サーバーを作成した後にソケットが置き換えられていれば削除しません。

このメソッドの引数についての詳細は loop.create_server() メソッドのドキュメントを参照してください。

バージョン 3.7 で変更: ssl_handshake_timeout と start_serving パラメーターが追加されました。 path パラメーターに Path オブジェクトを指定できるようになりました。

バージョン 3.11 で変更: ssl_shutdown_timeout パラメータが追加されました。

バージョン 3.13 で変更: cleanup_socket パラメーターが追加されました。

async loop.connect_accepted_socket(protocol_factory, sock, *, ssl=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None)

すでに確立した接続を transport と protocol のペアでラップします。

このメソッドは asyncio の範囲外で確立された接続を使うサーバーに対しても使えますが、その場合でも接続は asyncio を使って処理されます。

引数:

  • protocol_factory は asyncio プロトコル の実装を返す呼び出し可能オブジェクトでなければなりません。

  • sock は socket.accept メソッドが返す既存のソケットオブジェクトです。

    注釈

    sock 引数を渡すと、ソケットの所有権は作成されたトランスポートに移ります。 ソケットを閉じるには、トランスポートの close() メソッドを呼び出してください。

  • ssl には SSLContext を指定できます。指定すると、受け付けたコネクション上での SSL を有効にします。

  • ssl_handshake_timeout は SSL ハンドシェイクが完了するまでの (SSL 接続のための) 待ち時間を秒単位で指定します。 None が与えられた場合はデフォルト値 60.0 が使われます。

  • ssl_shutdown_timeout は、接続を中断する前に SSL の終了処理を待つ時間を秒単位で指定します。 None (デフォルト) の場合は 30.0 秒です。

(transport, protocol) のペアを返します。

Added in version 3.5.3.

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

バージョン 3.11 で変更: ssl_shutdown_timeout パラメータが追加されました。

ファイルの転送

async loop.sendfile(transport, file, offset=0, count=None, *, fallback=True)

transport を通じて file を送信します。送信したデータの総バイト数を返します。

このメソッドは、もし利用可能であれば高性能な os.sendfile() を利用します。

file はバイナリモードでオープンされた通常のファイルオブジェクトでなければなりません。

offset はファイルの読み込み開始位置を指定します。 count が指定された場合、ファイルの EOF までファイルを送信する代わりに、 count で指定された総バイト数の分だけ送信します。ファイルオブジェクトが指し示す位置は、メソッドがエラーを送出した場合でも更新されます。この場合実際に送信されたバイト数は file.tell() メソッドで取得することができます。

fallback を True に指定することで、 asyncio がプラットフォームが sendfile システムコールをサポートしていない場合 (たとえば Windows や Unix の SSL ソケットなど) に別の方法でファイルの読み込みと送信を行うようにすることができます。

システムが sendfile システムコールをサポートしておらず、かつ fallback が False の場合、 SendfileNotAvailableError 例外を送出します。

Added in version 3.7.

TLS へのアップグレード

async loop.start_tls(transport, protocol, sslcontext, *, server_side=False, server_hostname=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None)

既存のトランスポートベースの接続を TLS にアップグレードします。

TLS のエンコード・デコードを行うインスタンスを作成し、transport と protocol の間に挿入します。 このインスタンスは、transport に対するプロトコルと、protocol に対するトランスポートの両方のインターフェースを実装します。

作成した、二つのインターフェースを持つインスタンスを返します。 await の後、protocol は元の transport の使用をやめ、返されたオブジェクトだけを使って通信する必要があります。 エンコーダーが protocol 側のデータをキャッシュし、必要に応じて追加の TLS セッションパケットを transport と交換するためです。

渡されたトランスポートがすでに終了処理中である場合など、状況によっては None を返すことがあります。

引数:

  • transport と protocol には、 create_server() や create_connection() が返すものと同等のインスタンスを指定します。

  • sslcontext: 構成済みの SSLContext インスタンスです。

  • (create_server() で生成されたような) サーバーサイドの接続をアップグレードする場合は server_side に True を渡します。

  • server_hostname: 対象のサーバーの証明書との照合に使われるホスト名を設定または上書きします。

  • ssl_handshake_timeout は TLS ハンドシェイクが完了するまでの (TLS 接続のための) 待ち時間を秒単位で指定します。指定した待ち時間を超えると接続は中断します。 None が与えられた場合はデフォルト値 60.0 が使われます。

  • ssl_shutdown_timeout は、接続を中断する前に SSL の終了処理を待つ時間を秒単位で指定します。 None (デフォルト) の場合は 30.0 秒です。

Added in version 3.7.

バージョン 3.11 で変更: ssl_shutdown_timeout パラメータが追加されました。

ファイル記述子の監視

loop.add_reader(fd, callback, *args)

ファイル記述子 fd に対する読み込みが可能かどうかの監視を開始し、 fd が読み込み可能になると、指定した引数でコールバック callback を呼び出します。

fd にすでに登録されているコールバックがあれば、キャンセルして callback に置き換えます。

loop.remove_reader(fd)

ファイル記述子 fd が読み込み可能になるのを監視する処理を停止します。 それまで fd の読み込みを監視していた場合は True を返します。

loop.add_writer(fd, callback, *args)

ファイル記述子 fd が書き込み可能になるのを監視し始めます。 書き込み可能になると、指定した引数 args で callback を呼び出します。

fd にすでに登録されているコールバックがあれば、キャンセルして callback に置き換えます。

コールバック callback に キーワード引数を渡す 場合は functools.partial() を使ってください。

loop.remove_writer(fd)

ファイル記述子 fd が書き込み可能になるのを監視する処理を停止します。 それまで fd の書き込みを監視していた場合は True を返します。

これらのメソッドに対する制限事項については プラットフォームのサポート状況 節も参照してください。

ソケットオブジェクトと直接やりとりする

一般に、 loop.create_connection() や loop.create_server() のようなトランスポートベースの API を使ったプロトコルの実装はソケットと直接やり取りする実装に比べて高速です。しかしながら、パフォーマンスが重要でなく、直接 socket オブジェクトとやりとりした方が便利なユースケースがいくつかあります。

async loop.sock_recv(sock, nbytes)

nbytes で指定したバイト数までのデータをソケット sock から受信します。 このメソッドは socket.recv() の非同期版です。

受信したデータをバイトオブジェクトとして返します。

sock はノンブロッキングソケットでなければなりません。

バージョン 3.7 で変更: このメソッドは常にコルーチンメソッドとしてドキュメントに記載されてきましたが、 Python 3.7 より前のリリースでは Future オブジェクトを返していました。 Python 3.7 からは async def メソッドになりました。

async loop.sock_recv_into(sock, buf)

ソケット sock からデータを受信してバッファ buf に格納します。ブロッキングコードの socket.recv_into() メソッドをモデルとしています。

バッファに書き込んだデータのバイト数を返します。

sock はノンブロッキングソケットでなければなりません。

Added in version 3.7.

async loop.sock_recvfrom(sock, bufsize)

sock から最大 bufsize バイトのデータグラムを受信します。 socket.recvfrom() の非同期版です。

(受信したデータ, 送信元アドレス) のタプルを返します。

sock はノンブロッキングソケットでなければなりません。

Added in version 3.11.

async loop.sock_recvfrom_into(sock, buf, nbytes=0)

sock から最大 nbytes バイトのデータグラムを受信し、buf に格納します。 socket.recvfrom_into() の非同期版です。

(受信したバイト数, 送信元アドレス) のタプルを返します。

sock はノンブロッキングソケットでなければなりません。

Added in version 3.11.

async loop.sock_sendall(sock, data)

データ data をソケット sock に送信します。 socket.sendall() メソッドの非同期版です。

このメソッドは data をすべて送信し終えるか、またはエラーが起きるまでデータをソケットに送信し続けます。送信に成功した場合 None を返します。エラーの場合は例外が送出されます。エラーとなった場合、接続の受信側で正しく処理されたデータの総量を特定する方法はありません。

sock はノンブロッキングソケットでなければなりません。

バージョン 3.7 で変更: このメソッドは常にコルーチンメソッドとしてドキュメントに記載されてきましたが、 Python 3.7 より前のリリースでは Future オブジェクトを返していました。 Python 3.7 からは async def メソッドになりました。

async loop.sock_sendto(sock, data, address)

sock から address にデータグラムを送信します。 socket.sendto() の非同期版です。

送信したバイト数を返します。

sock はノンブロッキングソケットでなければなりません。

Added in version 3.11.

async loop.sock_connect(sock, address)

ソケット sock をアドレス address のリモートソケットに接続します。

socket.connect() の非同期版です。

sock はノンブロッキングソケットでなければなりません。

SelectorEventLoop では、address を事前に名前解決する必要はありません。 AF_INET と AF_INET6 のソケットでは、sock_connect はまず socket.inet_pton() で address が解決済みかどうかを確認し、未解決なら loop.getaddrinfo() で解決します。

Windows のデフォルトである ProactorEventLoop は、address の名前解決を行いません。 ホストは数値の IP アドレスでなければならず、ホスト名を渡すと OSError を送出します。 先に loop.getaddrinfo() でアドレスを解決するか、すべてのプラットフォームで名前解決を行う loop.create_connection() を使ってください。

バージョン 3.5.2 で変更: SelectorEventLoop では、address を事前に名前解決する必要がなくなりました。

async loop.sock_accept(sock)

接続を受け付けます。ブロッキングコールの socket.accept() メソッドをモデルとしています。

ソケットはアドレスに束縛済みで、接続を listen 中である必要があります。戻り値は (conn, address) のペアで、conn は接続を通じてデータの送受信を行うための 新しい ソケットオブジェクト、address は接続先の端点でソケットに束縛されているアドレスを示します。

sock はノンブロッキングソケットでなければなりません。

バージョン 3.7 で変更: このメソッドは常にコルーチンメソッドとしてドキュメントに記載されてきましたが、 Python 3.7 より前のリリースでは Future オブジェクトを返していました。 Python 3.7 からは async def メソッドになりました。

参考

loop.create_server() および start_server()。

async loop.sock_sendfile(sock, file, offset=0, count=None, *, fallback=True)

ファイルを送信します。利用可能なら高性能な os.sendfile を使います。送信したデータの総バイト数を返します。

socket.sendfile() メソッドの非同期版です。

sock は socket.SOCK_STREAM タイプのノンブロッキングな socket でなければなりません。

file はバイナリモードでオープンされた通常のファイルオブジェクトでなければなりません。

offset はファイルの読み込み開始位置を指定します。 count が指定された場合、ファイルの EOF までファイルを送信する代わりに、 count で指定された総バイト数の分だけ送信します。ファイルオブジェクトが指し示す位置は、メソッドがエラーを送出した場合でも更新されます。この場合実際に送信されたバイト数は file.tell() メソッドで取得することができます。

fallback が True に設定された場合、 プラットフォームが sendfile システムコールをサポートしていない場合 (たとえば Windows や Unix の SSL ソケットなど) に asyncio が別の方法でファイルの読み込みと送信を行うようにすることができます。

システムが sendfile システムコールをサポートしておらず、かつ fallback が False の場合、 SendfileNotAvailableError 例外を送出します。

sock はノンブロッキングソケットでなければなりません。

Added in version 3.7.

DNS

async loop.getaddrinfo(host, port, *, family=0, type=0, proto=0, flags=0)

socket.getaddrinfo() の非同期版です。

async loop.getnameinfo(sockaddr, flags=0)

socket.getnameinfo() の非同期版です。

注釈

getaddrinfo と getnameinfo は、内部ではループのデフォルトのスレッドプール Executor を通じて同期版を呼び出します。 この Executor に空きがなくなると処理が遅れ、高水準のネットワークライブラリでタイムアウトが増えることがあります。 これを軽減するには、他のユーザー処理に別の Executor を使うか、ワーカー数の多い Executor をデフォルトに設定することを検討してください。

バージョン 3.7 で変更: getaddrinfo と getnameinfo の2つのメソッドは、いずれも常にコルーチンメソッドとしてドキュメントに記載されてきましたが、 Python 3.7 より前のリリースでは、実際には asyncio.Future オブジェクトを返していました。 Python 3.7 からはどちらのメソッドもコルーチンになりました。

パイプとやりとりする

async loop.connect_read_pipe(protocol_factory, pipe)

pipe の読み込み側の終端をイベントループに登録します。

protocol_factory は asyncio プロトコル の実装を返す呼び出し可能オブジェクトでなければなりません。

pipe は ファイルライクオブジェクト です。 指定できるオブジェクトについては サポートされるパイプオブジェクト を参照してください。

(transport, protocol) のペアを返します。ここで transport は ReadTransport のインターフェースをサポートし、 protocol は protocol_factory ファクトリでインスタンス化されたオブジェクトです。

SelectorEventLoop イベントループでは、pipe が非ブロックモードに設定されます。

async loop.connect_write_pipe(protocol_factory, pipe)

pipe の書き込み側終端をイベントループに登録します。

protocol_factory は asyncio プロトコル の実装を返す呼び出し可能オブジェクトでなければなりません。

pipe は ファイルライクオブジェクト です。 指定できるオブジェクトについては サポートされるパイプオブジェクト を参照してください。

(transport, protocol) のペアを返します。ここで transport は WriteTransport のインスタンスであり、 protocol は protocol_factory ファクトリでインスタンス化されたオブジェクトです。

SelectorEventLoop イベントループでは、pipe が非ブロックモードに設定されます。

サポートされるパイプオブジェクト

これらのメソッドで扱えるのは、OS が読み書きの準備状況をポーリングできるオブジェクト、またはオーバーラップ I/O を実行できるオブジェクトだけです。 ディスク上の通常のファイルは、どのプラットフォームでも サポートされません。 asyncio に非同期ファイル I/O はないため、イベントループをブロックせずに通常のファイルを読み書きするには loop.run_in_executor() を使ってください。

Unix の SelectorEventLoop では、pipe は次のいずれかをラップする必要があります。

  • os.pipe() で作成したペアの一端や、os.mkfifo() で作成した FIFO などのパイプ

  • ソケット

  • 端末などのキャラクターデバイス

Windows では、これらのメソッドを実装しているのは ProactorEventLoop だけです。 ハンドルを I/O 完了ポートに関連付ける必要があるため、pipe はオーバーラップ I/O 用に開かれたハンドル (FILE_FLAG_OVERLAPPED フラグで作成したもの) をラップしなければなりません。 オーバーラップ I/O 用に開かれていないハンドルは拒否されます。 特に、標準ストリーム (sys.stdin、sys.stdout、sys.stderr)、コンソールのハンドル、os.pipe() で作成したパイプは、オーバーラップ I/O 用には開かれていないため、これらのメソッドでは 使えません。

注釈

SelectorEventLoop は Windows 上で上記のメソッドをサポートしていません。 Windowsでは代わりに ProactorEventLoop を使ってください。

参考

loop.subprocess_exec() および loop.subprocess_shell() メソッド。

Unix シグナル

loop.add_signal_handler(signum, callback, *args)

callback をシグナル signum のハンドラーに設定し、args を位置引数として渡します。

このコールバックは、キューに入っている他のコールバックや実行可能なコルーチンとともに、イベントループ loop によって呼び出されます。 signal.signal() で登録したシグナルハンドラとは異なり、この関数で登録したコールバックはイベントループとやりとりできます。

シグナルナンバーが誤っているか捕捉不可能な場合 ValueError が送出されます。ハンドラーの設定に問題があった場合 RuntimeError が送出されます。

コールバック callback に キーワード引数を渡す 場合は functools.partial() を使ってください。

signal.signal() と同じく、この関数はメインスレッドから呼び出されなければなりません。

loop.remove_signal_handler(sig)

シグナル sig に対するハンドラを削除します。

シグナルハンドラが削除された場合 True を返します。シグナルに対してハンドラが設定されていない場合には False を返します。

参考

signal モジュール。

スレッドまたはプロセスプールでコードを実行する

awaitable loop.run_in_executor(executor, func, *args)

指定した Executor 内で、args を位置引数として func を呼び出すように手配します。

executor 引数には concurrent.futures.Executor のインスタンスを指定します。 None の場合はデフォルトの Executor を使います。 デフォルトの Executor は loop.set_default_executor() で設定できます。 設定しなければ、run_in_executor() が必要になった時点で concurrent.futures.ThreadPoolExecutor を初期化して使います。

以下はプログラム例です:

import asyncio
import concurrent.futures

def blocking_io():
    # ログ記録などのファイル操作はイベントループをブロックする
    # 可能性があるので、スレッドプールで実行する。
    with open('/dev/urandom', 'rb') as f:
        return f.read(100)

def cpu_bound():
    # CPU バウンドな処理はイベントループをブロックする。
    # 通常はプロセスプールで実行する方がよい。
    return sum(i * i for i in range(10 ** 7))

async def main():
    loop = asyncio.get_running_loop()

    ## 実行方法:

    # 1. ループのデフォルトの Executor で実行する:
    result = await loop.run_in_executor(
        None, blocking_io)
    print('default thread pool', result)

    # 2. 自分で作成したスレッドプールで実行する:
    with concurrent.futures.ThreadPoolExecutor() as pool:
        result = await loop.run_in_executor(
            pool, blocking_io)
        print('custom thread pool', result)

    # 3. 自分で作成したプロセスプールで実行する:
    with concurrent.futures.ProcessPoolExecutor() as pool:
        result = await loop.run_in_executor(
            pool, cpu_bound)
        print('custom process pool', result)

    # 4. 自分で作成したインタープリタプールで実行する:
    with concurrent.futures.InterpreterPoolExecutor() as pool:
        result = await loop.run_in_executor(
            pool, cpu_bound)
        print('custom interpreter pool', result)

if __name__ == '__main__':
    asyncio.run(main())

例の 3 番では、ProcessPoolExecutor が使う multiprocessing の特性により、エントリーポイントのガード (if __name__ == '__main__') が必要です。 メインモジュールの安全なインポート を参照してください。

このメソッドは asyncio.Future オブジェクトを返します。

関数 func に キーワード引数を渡す 場合は functools.partial() を使ってください。

バージョン 3.5.3 で変更: loop.run_in_executor() は内部で生成するスレッドプールエグゼキュータの max_workers を設定せず、代わりにスレッドプールエグゼキュータ (ThreadPoolExecutor) にデフォルト値を設定させるようになりました。

loop.set_default_executor(executor)

executor を、run_in_executor() が使うデフォルトの Executor に設定します。 executor は ThreadPoolExecutor のインスタンスでなければなりません。 これには InterpreterPoolExecutor も含まれます。

バージョン 3.11 で変更: executor は ThreadPoolExecutor のインスタンスでなければならなくなりました。

エラー処理 API

イベントループ内での例外の扱い方をカスタマイズできます。

loop.set_exception_handler(handler)

handler を新しいイベントループ例外ハンドラーとして設定します。

handler が None の場合、デフォルトの例外ハンドラが設定されます。そうでなければ、 handler は (loop, context) に一致する関数シグネチャを持った呼び出し可能オブジェクトでなければなりません。ここで loop はアクティブなイベントループへの参照であり、 context は例外の詳細な記述からなる dict オブジェクトです (context についての詳細は call_exception_handler() メソッドのドキュメントを参照してください)。

Task または Handle のためにハンドラーを呼び出す場合、そのタスクまたはコールバックハンドルの contextvars.Context で実行します。

バージョン 3.12 で変更: 例外が発生したタスクまたはハンドルの Context で、ハンドラーを呼び出す場合があるようになりました。

loop.get_exception_handler()

現在の例外ハンドラを返します。カスタム例外ハンドラが設定されていない場合は None を返します。

Added in version 3.5.2.

loop.default_exception_handler(context)

デフォルトの例外ハンドラーです。

デフォルト例外ハンドラは、例外ハンドラが未設定の場合、例外が発生した時に呼び出されます。デフォルト例外ハンドラの挙動を受け入れるために、カスタム例外ハンドラから呼び出すことも可能です。

引数 context の意味は call_exception_handler() と同じです。

loop.call_exception_handler(context)

現在のイベントループ例外ハンドラーを呼び出します。

context は以下のキーを含む dict オブジェクトです (将来の Python バージョンで新しいキーが追加される可能性があります):

  • 'message': エラーメッセージ;

  • 'exception' (任意): 例外オブジェクト;

  • 'future' (任意): asyncio.Future インスタンス;

  • 'task' (省略可能): asyncio.Task のインスタンス

  • 'handle' (任意): asyncio.Handle インスタンス;

  • 'protocol' (任意): プロトコル インスタンス;

  • 'transport' (任意): トランスポート インスタンス;

  • 'socket' (省略可能): socket.socket のインスタンス

  • 'source_traceback' (省略可能): 生成元のトレースバック

  • 'handle_traceback' (省略可能): ハンドルのトレースバック

  • 'asyncgen' (optional): Asynchronous generator that caused the exception.

注釈

イベントループのサブクラスで、このメソッドをオーバーライドしないでください。 例外処理をカスタマイズするには set_exception_handler() を使ってください。

デバッグモードの有効化

loop.get_debug()

イベントループのデバッグモード (bool) を取得します。

環境変数 PYTHONASYNCIODEBUG に空でない文字列が設定されている場合のデフォルト値は True、そうでない場合は False になります。

loop.set_debug(enabled: bool)

イベントループのデバッグモードを設定します。

バージョン 3.7 で変更: 新しい Python 開発モード を使ってデバッグモードを有効化することができるようになりました。

loop.slow_callback_duration

この属性は、「遅い」とみなす実行時間の最小値を秒単位で設定するために使います。 デバッグモードが有効な場合、「遅い」コールバックがログに記録されます。

デフォルト値は 100 ミリ秒です。

サブプロセスの実行

この節で解説しているのは低水準のメソッドです。通常の async/await コードでは、高水準の関数である asyncio.create_subprocess_shell() や asyncio.create_subprocess_exec() を代わりに使うことを検討してください。

注釈

Windows では、デフォルトの ProactorEventLoop はサブプロセスをサポートしますが、SelectorEventLoop はサポートしません。 詳細は Windows でのサブプロセスのサポート を参照してください。

async loop.subprocess_exec(protocol_factory, *args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)

args で指定されたひとつの、または複数の文字列引数からサブプロセスを生成します。

args は下記のいずれかに当てはまる文字列のリストでなければなりません:

引数の最初の文字列はプログラムの実行ファイルを指定します。それに続く残りの文字列は引数を指定し、そのプログラムに対する argv を構成します。

このメソッドは標準ライブラリの subprocess.Popen クラスを、 shell=False かつ最初の引数に文字列のリストを渡して呼び出した場合に似ています。しかし、 Popen クラスは文字列のリストを引数としてひとつだけ取るのに対して、 subprocess_exec は複数の文字列引数をとることができます。

protocol_factory は asyncio.SubprocessProtocol クラスの派生クラスを返す呼び出し可能オブジェクトでなければなりません。

その他の引数:

  • stdin は下記のいずれかをとることができます:

    • ファイルライクオブジェクト

    • 既存のファイル記述子 (正の整数)。 例えば os.pipe() で作成したもの。

    • デフォルト値は subprocess.PIPE 定数で、この場合新規にパイプを生成して接続します。

    • None が設定された場合、サブプロセスは元のプロセスのファイルデスクリプタを引き継ぎます。

    • subprocess.DEVNULL 定数を設定すると、特別なファイル os.devnull を使います。

  • stdout は下記のいずれかをとることができます:

    • ファイルライクオブジェクト

    • デフォルト値は subprocess.PIPE 定数で、この場合新規にパイプを生成して接続します。

    • None が設定された場合、サブプロセスは元のプロセスのファイルデスクリプタを引き継ぎます。

    • subprocess.DEVNULL 定数を設定すると、特別なファイル os.devnull を使います。

  • stderr は下記のいずれかをとることができます:

    • ファイルライクオブジェクト

    • デフォルト値は subprocess.PIPE 定数で、この場合新規にパイプを生成して接続します。

    • None が設定された場合、サブプロセスは元のプロセスのファイルデスクリプタを引き継ぎます。

    • subprocess.DEVNULL 定数を設定すると、特別なファイル os.devnull を使います。

    • subprocess.STDOUT 定数を設定すると、標準エラー出力ストリームをプロセスの標準出力ストリームに接続します。

  • その他のすべてのキーワード引数は解釈されずにそのまま subprocess.Popen に渡されます。ただし、 bufsize、 universal_newlines、 shell、 text、 encoding および errors は指定してはいけません。

    asyncio のサブプロセス API はストリームからテキストへのデコードをサポートしていません。ストリームからテキストに変換するには bytes.decode() 関数を使ってください。

stdin、stdout、stderr として渡したファイルライクオブジェクトがパイプを表す場合、イベントループで使うには、パイプのもう一方の端を connect_write_pipe() または connect_read_pipe() で登録してください。

他の引数についての詳細は subprocess.Popen クラスのコンストラクタを参照してください。

(transport, protocol) のペアを返します。ここで transport は asyncio.SubprocessTransport 基底クラスに適合するオブジェクトで、 protocol は protocol_factory によりインスタンス化されたオブジェクトです。

トランスポートを閉じた場合や、トランスポートがガベージコレクションで回収された場合、子プロセスがまだ実行中なら強制終了します。

async loop.subprocess_shell(protocol_factory, cmd, *, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)

コマンド cmd からプラットフォームの "シェル" シンタックスを使ってサブプロセスを生成します。 cmd は str 文字列もしくは ファイルシステムのエンコーディング でエンコードされた bytes 文字列です。

これは標準ライブラリの subprocess.Popen クラスを shell=True で呼び出した場合と似ています。

protocol_factory は SubprocessProtocol の派生クラスを返す呼び出し可能オブジェクトでなければなりません。

その他の引数についての詳細は subprocess_exec() メソッドを参照してください。

(transport, protocol) のペアを返します。ここで transport は SubprocessTransport 基底クラスに適合するオブジェクトで、 protocol は protocol_factory によりインスタンス化されたオブジェクトです。

トランスポートを閉じた場合や、トランスポートがガベージコレクションで回収された場合、子プロセスがまだ実行中なら強制終了します。

注釈

シェルインジェクション の脆弱性を回避するために全ての空白文字および特殊文字を適切にクオートすることは、アプリケーション側の責任で確実に行ってください。シェルコマンドを構成する文字列内の空白文字と特殊文字のエスケープは、 shlex.quote() 関数を使うと適切に行うことができます。

コールバックハンドル

class asyncio.Handle

loop.call_soon() や loop.call_soon_threadsafe() が返すコールバックのラッパーです。

get_context()

ハンドルに関連付けられた contextvars.Context オブジェクトを返します。

Added in version 3.12.

cancel()

コールバックをキャンセルします。コールバックがキャンセル済みまたは実行済みの場合、このメソッドは何の影響もありません。

cancelled()

コールバックがキャンセルされた場合 True を返します。

Added in version 3.7.

class asyncio.TimerHandle

A callback wrapper object returned by loop.call_later(), and loop.call_at().

このクラスは Handle の派生クラスです。

when()

コールバックのスケジュール時刻を秒単位の float で返します。

戻り値の時刻は絶対値で、 loop.time() と同じ参照時刻を使って定義されています。

Added in version 3.7.

サーバーオブジェクト

Server オブジェクトは loop.create_server()、 loop.create_unix_server()、 start_server() および start_unix_server() 関数により生成されます。

Server クラスを直接インスタンス化しないでください。

class asyncio.Server

Server オブジェクトは非同期のコンテキストマネージャです。 async with 文の中で使われた場合、 async with 文が完了した時に Server オブジェクトがクローズされること、およびそれ以降に接続を受け付けないことが保証されます。

srv = await loop.create_server(...)

async with srv:
    # 何らかの処理

# この時点で srv は閉じられており、新しい接続を受け付けない。

バージョン 3.7 で変更: Python 3.7 から、 Server オブジェクトは非同期のコンテキストマネージャになりました。

バージョン 3.11 で変更: このクラスは Python 3.9.11、3.10.3、3.11 で asyncio.Server として公開されました。

close()

サーバーを停止します: 待機しているソケットをクローズし sockets 属性に None を設定します。

既存の受信中のクライアントとの接続を表すソケットはオープンのままです。

サーバーは非同期に閉じられます。 サーバーが閉じられ、すべての接続が終了するまで待つには、wait_closed() コルーチンを使ってください。

close_clients()

受け付け済みのすべてのクライアント接続を閉じます。

関連付けられたすべてのトランスポートに対して close() を呼び出します。

新しいクライアント接続との競合を避けるため、サーバーを閉じる際は close_clients() の前に close() を呼び出してください。

Added in version 3.13.

abort_clients()

保留中の処理の完了を待たずに、受け付け済みのすべてのクライアント接続を即座に閉じます。

関連付けられたすべてのトランスポートに対して abort() を呼び出します。

新しいクライアント接続との競合を避けるため、サーバーを閉じる際は abort_clients() の前に close() を呼び出してください。

Added in version 3.13.

get_loop()

サーバオブジェクトに付随するイベントループを返します。

Added in version 3.7.

async start_serving()

接続の受け付けを開始します。

このメソッドはべき等なので、サーバーがすでに接続を受け付けていても呼び出せます。

キーワード専用のパラメータ start_serving を loop.create_server() や asyncio.start_server() メソッドに対して使用することにより、初期に接続を受け付けない Server オブジェクトを生成することができます。この場合 Server.start_serving() または Server.serve_forever() メソッドを使ってオブジェクトが接続の受け付けを開始するようにすることができます。

Added in version 3.7.

async serve_forever()

接続の受け入れを開始し、コルーチンがキャンセルされるまで継続します。 serve_forever タスクのキャンセルによりサーバーもクローズされます。

このメソッドはサーバーがすでに接続の受け入れを開始していても呼び出し可能です。ひとつの Server オブジェクトにつき serve_forever タスクはひとつだけ存在できます。

以下はプログラム例です:

async def client_connected(reader, writer):
    # reader/writer ストリームでクライアントと通信する。
    # 例えば次のようにする:
    await reader.readline()

async def main(host, port):
    srv = await asyncio.start_server(
        client_connected, host, port)
    await srv.serve_forever()

asyncio.run(main('127.0.0.1', 0))

Added in version 3.7.

is_serving()

サーバーが新規に接続の受け入れを開始した場合 True を返します。

Added in version 3.7.

async wait_closed()

close() メソッドが完了し、すべてのアクティブな接続が終了するまで待ちます。

バージョン 3.12 で変更: wait_closed() は、サーバーが閉じられ、すべてのアクティブな接続が終了するまで待つようになりました。 以前は、サーバーがすでに閉じられていると、接続がまだ残っていても即座に返っていました。

sockets

List of socket-like objects, asyncio.trsock.TransportSocket, which the server is listening on.

バージョン 3.7 で変更: Python 3.7 より前のバージョンでは、 Server.sockets は内部に持っているサーバーソケットのリストを直接返していました。 Python 3.7 ではリストのコピーが返されるようになりました。

イベントループの実装

asyncio は2つの異なるイベントループの実装、 SelectorEventLoop と ProactorEventLoop、 を提供します:

デフォルトでは、asyncio は EventLoop を使うように設定されています。

class asyncio.SelectorEventLoop

selectors モジュールに基づく AbstractEventLoop のサブクラスです。

プラットフォーム上で利用可能な最も効率の良い selector を使います。特定のセレクタ実装を使うように手動で構成することも可能です:

import asyncio
import selectors

async def main():
   ...

loop_factory = lambda: asyncio.SelectorEventLoop(selectors.SelectSelector())
asyncio.run(main(), loop_factory=loop_factory)

利用可能な環境: Unix, Windows.

class asyncio.ProactorEventLoop

I/O 完了ポート (IOCP) を使う、Windows 用の AbstractEventLoop のサブクラスです。

class asyncio.EventLoop

そのプラットフォームで利用可能な、最も効率的な AbstractEventLoop のサブクラスの別名です。

Unix では SelectorEventLoop、Windows では ProactorEventLoop の別名です。

Added in version 3.13.

class asyncio.AbstractEventLoop

asyncio に適合するイベントループの抽象基底クラスです。

イベントループのメソッド の節には、AbstractEventLoop の代替実装で定義すべきメソッドをすべて列挙しています。

使用例

この節の全ての使用例は 意図的に loop.run_forever() や loop.call_soon() のような 低水準のイベントループ API の使用法を示しています。一方で現代的な asyncio アプリケーションはここに示すような方法をほとんど必要としません。 asyncio.run() のような高水準の関数の使用を検討してください。

call_soon() を使った Hello World

loop.call_soon() メソッドを使ってコールバックをスケジュールする例です。コールバックは "Hello World" を出力しイベントループを停止します:

import asyncio

def hello_world(loop):
    """'Hello World' を表示してイベントループを停止するコールバック"""
    print('Hello World')
    loop.stop()

loop = asyncio.new_event_loop()

# hello_world() の呼び出しをスケジュールする
loop.call_soon(hello_world, loop)

# loop.stop() で終了するブロッキング呼び出し
try:
    loop.run_forever()
finally:
    loop.close()

参考

コルーチンと run() 関数を使用した同じような Hello World の例。

call_later() で現在の日時を表示する

毎秒現在時刻を表示するコールバックの例です。コールバックは loop.call_later() メソッドを使って自身を5秒後に実行するよう再スケジュールし、イベントループを停止します:

import asyncio
import datetime as dt

def display_date(end_time, loop):
    print(dt.datetime.now())
    if (loop.time() + 1.0) < end_time:
        loop.call_later(1, display_date, end_time, loop)
    else:
        loop.stop()

loop = asyncio.new_event_loop()

# display_date() の最初の呼び出しをスケジュールする
end_time = loop.time() + 5.0
loop.call_soon(display_date, end_time, loop)

# loop.stop() で終了するブロッキング呼び出し
try:
    loop.run_forever()
finally:
    loop.close()

参考

コルーチンと run() 関数を使用した同じような 現在時刻出力 の例。

読み込みイベント用ファイル記述子の監視

ファイル記述子が loop.add_reader() メソッドを使って何らかのデータを受信するまで待機し、その後イベントループをクローズします:

import asyncio
from socket import socketpair

# 接続されたファイル記述子のペアを作成する
rsock, wsock = socketpair()

loop = asyncio.new_event_loop()

def reader():
    data = rsock.recv(100)
    print("Received:", data.decode())

    # 処理が済んだので、ファイル記述子の登録を解除する
    loop.remove_reader(rsock)

    # イベントループを停止する
    loop.stop()

# 読み込みイベント用にファイル記述子を登録する
loop.add_reader(rsock, reader)

# ネットワークからのデータ受信を模倣する
loop.call_soon(wsock.send, 'abc'.encode())

try:
    # イベントループを実行する
    loop.run_forever()
finally:
    # 処理が済んだので、ソケットとイベントループを閉じる。
    rsock.close()
    wsock.close()
    loop.close()

参考

SIGINT および SIGTERM 用のシグナルハンドラーの設定

(この signal の例は Unix でのみ動作します。)

loop.add_signal_handler() メソッドで、シグナル SIGINT と SIGTERM のハンドラーを登録します。

import asyncio
import functools
import os
import signal

def ask_exit(signame, loop):
    print("got signal %s: exit" % signame)
    loop.stop()

async def main():
    loop = asyncio.get_running_loop()

    for signame in {'SIGINT', 'SIGTERM'}:
        loop.add_signal_handler(
            getattr(signal, signame),
            functools.partial(ask_exit, signame, loop))

    await asyncio.sleep(3600)

print("Event loop running for 1 hour, press Ctrl+C to interrupt.")
print(f"pid {os.getpid()}: send SIGINT or SIGTERM to exit.")

asyncio.run(main())