18.4. selectors — 高水準の I/O 多重化

バージョン 3.4 で追加.

ソースコード: Lib/selectors.py


18.4.1. はじめに

このモジュールにより、select モジュールプリミティブに基づく高水準かつ効率的な I/O の多重化が行えます。OS 水準のプリミティブを使用した正確な制御を求めない限り、このモジュールの使用が推奨されます。

このモジュールは BaseSelector 抽象基底クラスと、いくつかの具象実装 (KqueueSelector, EpollSelector...) を定義しており、これらは複数のファイルオブジェクトの I/O の準備状況の通知の待機に使用できます。以下では、 “ファイルオブジェクト” は、fileno() メソッドを持つあらゆるオブジェクトか、あるいは Raw ファイル記述子を意味します。ファイルオブジェクト を参照してください。

DefaultSelector は、現在のプラットフォームで利用できる、もっとも効率的な実装の別名になります: これはほとんどのユーザーにとってのデフォルトの選択になるはずです。

注釈

プラットフォームごとにサポートされているファイルオブジェクトのタイプは異なります: Windows ではソケットはサポートされますが、パイプはされません。Unix では両方がサポートされます (その他の fifo やスペシャルファイルデバイスなどのタイプもサポートされます)。

参考

select

低水準の I/O 多重化モジュールです。

18.4.2. クラス

クラス階層:

BaseSelector
+-- SelectSelector
+-- PollSelector
+-- EpollSelector
+-- DevpollSelector
+-- KqueueSelector

以下では、events は与えられたファイルオブジェクトを待機すべき I/O イベントを示すビット単位のマスクになります。これには以下のモジュール定数の組み合わせを設定できます:

定数

意味

EVENT_READ

読み込み可能

EVENT_WRITE

書き込み可能

class selectors.SelectorKey

SelectorKey はそれの下層のファイル記述子、選択したイベントマスク、および付属データへのファイルオブジェクトの関連付けに使用される namedtuple です。いくつかの BaseSelector メソッドを返します。

fileobj

登録されたファイルオブジェクトです。

fd

下層のファイル記述子です。

events

このファイルオブジェクトで待機しなければならないイベントです。

data

このファイルオブジェクトに関連付けられた任意の不透明型 (Opaque) データです: 例えば、これはクライアントごとのセッション ID の格納に使用が考えられます。

class selectors.BaseSelector

BaseSelector は複数のファイルオブジェクトの I/O イベントの準備状況の待機に使用されます。これはファイルストリームの登録、登録解除、およびこれらのストリームでの I/O イベントを待機 (任意でのタイムアウト) するメソッドをサポートします。これは抽象基底クラスであるため、インスタンスを作成できません。使用する実装を明示的に指定したい、そしてプラットフォームがそれをサポートしている場合は、代わりに DefaultSelector か、SelectSelector の中の一つや KqueueSelector などを使用します。BaseSelector とその具象実装は コンテキストマネージャー プロトコルをサポートしています。

abstractmethod register(fileobj, events, data=None)

I/O イベントを監視するファイルオブジェクトをセレクションに登録します。

fileobj は監視するファイルオブジェクトです。これは整数のファイル記述子か、fileno() メソッドを持つオブジェクトのどちらかになります。events は監視するイベントのビット幅マスクになります。data は不透明型 (Opaque) オブジェクトです。

これは新しい SelectorKey インスタンスを返します。不正なイベントマスク化ファイル記述子のときは ValueError が、ファイルオブジェクトがすでに登録済みのときは KeyError が送出されます。

abstractmethod unregister(fileobj)

ファイルオブジェクトのセレクション登録を解除し、監視対象から外します。ファイルオブジェクトの登録解除はそのクローズより前に行われます。

fileobj は登録済みのファイルオブジェクトでなければなりません。

関連付けられた SelectorKey インスタンスを返します。 fileobj が登録されていない場合 KeyError を送出します。 fileobj が不正 (例えば fileobjfileno() メソッドが無い場合や fileno() メソッドの戻り値が不正な場合) ValueError を送出します。

modify(fileobj, events, data=None)

登録されたファイルオブジェクトの監視されたイベントや付属データを変更します。

より効率的に実装できる点を除けば、 BaseSelector.unregister(fileobj)() に続けて BaseSelector.register(fileobj, events, data)() を行うのと等価です。

新たな SelectorKey インスタンスを返します。 イベントマスクやファイル記述子が不正な場合は ValueError を、ファイルオブジェクトが登録されていない場合は KeyError を送出します。

abstractmethod select(timeout=None)

登録されたいくつかのファイルオブジェクトが準備できたか、タイムアウトするまで待機します。

timeout > 0 の場合、最大待機時間を秒で指定します。 timeout <= 0 の場合、この関数の呼び出しはブロックせず、 現在準備できているファイルオブジェクトを報告します。 timeoutNone の場合、監視しているファイルオブジェクトの一つが準備できるまでブロックします。

この関数は (key, events) タプルのリストを返します。準備できたファイルオブジェクトにつき1タプルです。

key は準備状態のファイルオブジェクトに対応する SelectorKey インスタンスです。 events そのファイルオブジェクトで準備できたイベントのビットマスクです。

注釈

This method can return before any file object becomes ready or the timeout has elapsed if the current process receives a signal: in this case, an empty list will be returned.

バージョン 3.5 で変更: The selector is now retried with a recomputed timeout when interrupted by a signal if the signal handler did not raise an exception (see PEP 475 for the rationale), instead of returning an empty list of events before the timeout.

close()

セレクタを閉じます。

下層の資源が解放されたこと保証するために呼ばれなければなりません。 セレクタは一旦閉じられると使ってはいけません。

get_key(fileobj)

登録されたファイルオブジェクトに関連付けられたキーを返します。

そのファイルオブジェクトに関連付けられた SelectorKey インスタンスを返します。そのファイルオブジェクトが登録されていない場合 KeyError を送出します。

abstractmethod get_map()

ファイルオブジェクトからセレクタキーへのマッピングを返します。

This returns a Mapping instance mapping registered file objects to their associated SelectorKey instance.

class selectors.DefaultSelector

デフォルトの selector クラスで、現在のプラットフォームで利用できる最も効率的な実装を使用しています。大半のユーザはこれをデフォルトにすべきです。

class selectors.SelectSelector

select.select() を基底とするセレクタです。

class selectors.PollSelector

select.poll() を基底とするセレクタです。

class selectors.EpollSelector

select.epoll() を基底とするセレクタです。

fileno()

下層の select.epoll() オブジェクトが使用しているファイル記述子を返します。

class selectors.DevpollSelector

select.devpoll() を基底とするセレクタです。

fileno()

下層の select.devpoll() オブジェクトが使用しているファイル記述子を返します。

バージョン 3.5 で追加.

class selectors.KqueueSelector

select.kqueue() を基底とするセレクタです。

fileno()

下層の select.kqueue() オブジェクトが使用しているファイル記述子を返します。

18.4.3. 使用例

簡単なエコーサーバの実装です:

import selectors
import socket

sel = selectors.DefaultSelector()

def accept(sock, mask):
    conn, addr = sock.accept()  # Should be ready
    print('accepted', conn, 'from', addr)
    conn.setblocking(False)
    sel.register(conn, selectors.EVENT_READ, read)

def read(conn, mask):
    data = conn.recv(1000)  # Should be ready
    if data:
        print('echoing', repr(data), 'to', conn)
        conn.send(data)  # Hope it won't block
    else:
        print('closing', conn)
        sel.unregister(conn)
        conn.close()

sock = socket.socket()
sock.bind(('localhost', 1234))
sock.listen(100)
sock.setblocking(False)
sel.register(sock, selectors.EVENT_READ, accept)

while True:
    events = sel.select()
    for key, mask in events:
        callback = key.data
        callback(key.fileobj, mask)