selectors
— 高级 I/O 多路复用¶
3.4 版新增。
源代码: Lib/selectors.py
简介¶
此模块允许进行高级且高效的 I/O 多路复用,它构建在 select
模块原语之上。鼓励用户使用此模块,除非他们想要精确控制所使用的操作系统级原语。
它定义了一个 BaseSelector
抽象基类,以及几个具体实现(KqueueSelector
、EpollSelector
等),可用于等待多个文件对象上的 I/O 就绪通知。在下文中,“文件对象”指的是任何具有 fileno()
方法的对象,或原始文件描述符。请参阅 文件对象。
DefaultSelector
是当前平台上可用的最高效实现的别名:这应该是大多数用户的默认选择。
注意
支持的文件对象类型取决于平台:在 Windows 上,支持套接字,但不支持管道,而在 Unix 上,两者都支持(也可能支持其他一些类型,例如 fifo 或特殊文件设备)。
参见
select
低级 I/O 多路复用模块。
可用性:不支持 Emscripten,不支持 WASI。
此模块在 WebAssembly 平台 wasm32-emscripten
和 wasm32-wasi
上不可用或无法工作。有关更多信息,请参阅 WebAssembly 平台。
类¶
类层次结构
BaseSelector
+-- SelectSelector
+-- PollSelector
+-- EpollSelector
+-- DevpollSelector
+-- KqueueSelector
在下文中,*events* 是一个位掩码,指示应在给定文件对象上等待哪些 I/O 事件。它可以是以下模块常量的组合
- class selectors.SelectorKey¶
SelectorKey
是一个namedtuple
,用于将文件对象与其底层文件描述符、选定的事件掩码和附加数据相关联。它由多个BaseSelector
方法返回。- fileobj¶
已注册的文件对象。
- fd¶
底层文件描述符。
- events¶
必须在此文件对象上等待的事件。
- data¶
与此文件对象关联的不透明数据(可选):例如,这可用于存储每个客户端的会话 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* 是一个不透明对象。这将返回一个新的
SelectorKey
实例,如果事件掩码或文件描述符无效,则会引发ValueError
,如果文件对象已注册,则会引发KeyError
。
- abstractmethod unregister(fileobj)¶
取消注册文件对象以进行选择,将其从监视中移除。文件对象在关闭之前应先取消注册。
*fileobj* 必须是先前注册的文件对象。
这将返回关联的
SelectorKey
实例,如果 *fileobj* 未注册,则会引发KeyError
。如果 *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)
元组列表,每个就绪文件对象对应一个元组。key 是与就绪文件对象对应的
SelectorKey
实例。events 是此文件对象上就绪事件的位掩码。注意
如果当前进程接收到信号,则此方法可能会在任何文件对象变为就绪状态或超时之前返回:在这种情况下,将返回一个空列表。
在 3.5 版更改: 如果信号处理程序没有引发异常,则当选择器被信号中断时,现在将使用重新计算的超时时间重试选择器(有关基本原理,请参阅 PEP 475),而不是在超时之前返回一个空的事件列表。
- close()¶
关闭选择器。
必须调用此方法以确保释放任何底层资源。选择器一旦关闭,就不应再使用。
- get_key(fileobj)¶
返回与已注册文件对象关联的键。
这将返回与此文件对象关联的
SelectorKey
实例,如果文件对象未注册,则引发KeyError
。
- abstractmethod get_map()¶
返回文件对象到选择器键的映射。
这将返回一个
Mapping
实例,该实例将已注册的文件对象映射到与其关联的SelectorKey
实例。
- class selectors.DefaultSelector¶
默认选择器类,使用当前平台上可用的最高效实现。这应该是大多数用户的默认选择。
- 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)