"selectors" --- 高水準の I/O 多重化
***********************************

Added in version 3.4.

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

======================================================================


はじめに
========

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

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

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

注釈:

  対応するファイルオブジェクトの種類はプラットフォームによって異なりま
  す。 Windows ではソケットに対応していますがパイプには対応していませ
  ん。 Unix では両方に対応しています (FIFO や特殊デバイスファイルなど
  、他の種類にも対応している場合があります)。

参考:

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

利用可能な環境: not WASI.

このモジュールは WebAssembly では動作しないか、利用不可です。詳しくは
、WebAssembly プラットフォーム を見てください。


クラス
======

クラス階層:

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

以下では、*events* は指定したファイルオブジェクトで待機する I/O イベン
トを表すビットマスクです。 このモジュールの以下の定数を組み合わせて指
定できます。

   +-------------------------+-------------------------------------------------+
   | 定数                    | 意味                                            |
   |=========================|=================================================|
   | selectors.EVENT_READ    | 読み込み可能                                    |
   +-------------------------+-------------------------------------------------+
   | selectors.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()" オブジェクトが使用しているファイル記述
      子を返します。

   Added in version 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()  # 準備ができているはず
       print('accepted', conn, 'from', addr)
       conn.setblocking(False)
       sel.register(conn, selectors.EVENT_READ, read)

   def read(conn, mask):
       data = conn.recv(1000)  # 準備ができているはず
       if data:
           print('echoing', repr(data), 'to', conn)
           conn.send(data)  # ブロックしないことを期待
       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)
