# `selectors` --- 高水準の I/O 多重化

バージョン 3.4 で追加.

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

## はじめに

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

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

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

注釈

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

参考

`select`

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

## クラス

クラス階層:

    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 が不正な場合 (例えば fileobj に `fileno()` メソッドが無い場合や `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` の場合、この関数の呼び出しはブロックせず、 現在準備できているファイルオブジェクトを報告します。 timeout が `None` の場合、監視しているファイルオブジェクトの一つが準備できるまでブロックします。

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

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

    注釈

    このメソッドは、現在のプロセスで信号を受信した場合、どのファイルオブジェクトも準備完了にならないうちに、またはタイムアウトが経過する前に返ることがあります。その場合、空のリストが返されます。

    バージョン 3.5 で変更: このセレクタは、シグナルによって中断された時に、シグナルハンドラが例外を起こさなかった場合、空のイベントリストを返すのではなく、再計算されたタイムアウトによってリトライするようになりました (この論拠については PEP 475 を参照してください)。

  `close`()

    セレクタを閉じます。

    下層のリソースがすべて解放されたことを確かめるために呼ばれなければなりません。一旦閉じられたセレクタは使ってはいけません。

  `get_key`(fileobj)

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

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

  abstractmethod `get_map`()

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

    これは、登録済みのファイルオブジェクトを、それらに関連づけられた `SelectorKey` インスタンスにマッピングする `Mapping` のインスタンスを返します。

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()` オブジェクトが使用しているファイル記述子を返します。

## 使用例

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

    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)