selectors—高级 I/O 多路复用

3.4 版的新Function。

源代码: Lib/selectors.py


Introduction

此模块允许在select模块 Primitives 的基础上进行高层且高效的 I/O 复用。鼓励用户改用此模块,除非他们希望对使用的 OS 级 Primitives 进行精确控制。

它定义了一个BaseSelector抽象 Base Class,以及几个具体的实现(KqueueSelectorEpollSelector…),可用于 await 多个文件对象的 I/O 准备就绪通知。在下文中,“文件对象”是指具有fileno()方法或原始文件 Descriptors 的任何对象。参见file object

DefaultSelector是当前平台上可用的最高效实现的别名:这应该是大多数用户的默认选择。

Note

支持的文件对象的类型取决于平台:在 Windows 上,支持套接字,但不支持管道,而在 Unix 上,两者都受支持(还可以支持某些其他类型,例如 fifos 或特殊文件设备)。

See also

  • select

  • 低级 I/O 多路复用模块。

Classes

Classes hierarchy:

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

在下面,* events *是按位掩码,指示应在给定文件对象上 await 哪些 I/O 事件。它可以是以下模块常量的组合:

Note

ConstantMeaning
EVENT_READ可供阅读
EVENT_WRITE可写
  • 类别 selectors. SelectorKey

    • SelectorKeynamedtuple,用于将文件对象与其基础文件 Descriptors,选定的事件掩码和附加数据相关联。它由几种BaseSelector方法返回。
  • fileobj

    • 文件对象已注册。
  • fd

    • 基础文件 Descriptors。
  • events

    • 必须在此文件对象上 await 的事件。
  • data

    • 与此文件对象关联的可选不透明数据:例如,可以用于存储每个 Client 端会话 ID。
  • 类别 selectors. BaseSelector

    • BaseSelector用于 await 多个文件对象的 I/O 事件就绪。它支持文件流注册,注销和 await 这些流上的 I/O 事件的方法,并具有可选的超时时间。这是一个抽象的 Base Class,因此无法实例化。如果要专门使用实现,并且平台支持该实现,则使用DefaultSelectorSelectSelectorKqueueSelector等之一。 BaseSelector及其具体实现支持context manager协议。
  • 抽象方法 register(* fileobj 事件 data = None *)

    • 注册文件对象以供选择,并监视其 I/O 事件。
  • fileobj *是要监视的文件对象。它可以是整数文件 Descriptors,也可以是具有fileno()方法的对象。 * events *是要监视的事件的按位掩码。 * data *是不透明的对象。

这将返回一个新的SelectorKey实例,或者在事件掩码或文件 Descriptors 无效的情况下引发ValueError,如果文件对象已被注册则返回KeyError

  • 抽象方法 unregister(* fileobj *)
    • 从选择中取消注册文件对象,将其从监视中删除。文件对象在关闭之前应先注销。
  • fileobj *必须是先前注册的文件对象。

这将返回关联的SelectorKey实例,如果未注册* fileobj ,则引发KeyError。如果 fileobj *无效(例如,它没有fileno()方法或它的fileno()方法具有无效的返回值),它将引发ValueError

  • modify(* fileobj events data = None *)
    • 更改注册文件对象的监视事件或附加数据。

这等效于BaseSelector.unregister(fileobj)()后跟BaseSelector.register(fileobj, events, data)(),但可以更有效地实现它。

这将返回一个新的SelectorKey实例,或者在事件掩码或文件 Descriptors 无效的情况下引发ValueError,或者在未注册文件对象的情况下返回KeyError

  • 抽象方法 select(超时=无)
    • await 直到某些已注册的文件对象准备就绪,或者超时到期。

如果timeout > 0,则指定最大 await 时间,以秒为单位。如果timeout <= 0,则该调用将不会阻塞,并且将报告当前准备就绪的文件对象。如果* timeout *为None,则调用将阻塞,直到被监视的文件对象准备就绪为止。

这将返回一个(key, events)Tuples 的列表,每个就绪文件对象一个。

  • key *是与就绪文件对象相对应的SelectorKey实例。 * events *是此文件对象上准备好的事件的位掩码。

Note

如果当前进程收到 signal,则该方法可以在任何文件对象准备就绪或超时之前返回:在这种情况下,将返回一个空列表。

在版本 3.5 中进行了更改:现在,如果 signal 处理程序没有引发异常(请参阅 PEP 475),则被 signal break时,selectors 将被 signal break,并重新计算超时,而不是在超时之前返回空事件列表。

  • close ( )
    • 关闭 selectors。

必须调用它以确保释放任何基础资源。selectors 一旦关闭就不得使用。

  • get_key(* fileobj *)
    • 返回与已注册文件对象关联的密钥。

这将返回与此文件对象关联的SelectorKey实例,如果未注册文件对象,则返回KeyError

  • 抽象方法 get_map()
    • 返回文件对象到 selectors 键的 Map。

这将返回一个Mapping实例,该实例将注册的文件对象 Map 到其关联的SelectorKey实例。

  • 类别 selectors. DefaultSelector

    • 默认 selectors 类,使用当前平台上可用的最高效实现。对于大多数用户,这应该是默认选择。
  • 类别 selectors. SelectSelector

  • 类别 selectors. PollSelector

  • 类别 selectors. EpollSelector

  • fileno ( )

    • 这将返回基础select.epoll()对象使用的文件 Descriptors。
  • 类别 selectors. DevpollSelector

  • fileno ( )

3.5 版中的新Function。

Examples

这是一个简单的回显服务器实现:

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)