select --- 等待一组流上的事件¶
此模块提供了一些函数,可高效地等待一个或多个 流(实现流协议的类文件对象,如套接字、UART 和其他 I/O 对象)准备好读取或写入,而不必忙等待或在单个对象上阻塞。
poll 对象是推荐的接口:它可扩展到许多流,并且在通过 poll.ipoll() 使用时无需分配内存。模块级的 select() 函数则是一个效率较低的兼容性接口。
使用 poll 对象的示例:
import select
poller = select.poll()
poller.register(uart, select.POLLIN)
while True:
# Wait up to 1000 ms for the UART to have data.
for obj, event in poller.poll(1000):
if event & select.POLLIN:
print(obj.read())
使用模块级 select() 函数的示例:
import select
# Wait up to 1 second for the socket to become readable.
rlist, wlist, xlist = select.select([sock], [], [], 1.0)
if rlist:
data = sock.recv(100)
函数¶
- select.select(rlist: List, wlist: List, xlist: List, timeout: float | None = None) Tuple[List, List, List]¶
等待直到一个或多个给定的流对象准备就绪,或直到 timeout 到期。
rlist 是要监视其可读性的对象列表。
wlist 是要监视其可写性的对象列表。
xlist 是要监视其错误或挂断状况的对象列表。
timeout 是最大等待时间,以秒为单位(接受浮点数)。如果省略或为
None,则调用无限期阻塞;0表示立即返回(非阻塞轮询)。
返回一个由列表组成的三元组
(rlist, wlist, xlist)。每个返回的列表是对应输入列表的子集,分别包含已准备好读取、已准备好写入或发出错误/挂断信号的对象。如果 timeout 已过但没有任何对象就绪,则三个列表均为空。
常量¶
- select.POLLERR: int¶
流上发生了错误状况。这是一个非请求事件:即使未在 eventmask 中请求,它也会由
poll.poll()/poll.ipoll()报告,并且将其作为输入 eventmask 传入是无效的。
- select.POLLHUP: int¶
流已挂断/断开连接。这是一个非请求事件:即使未在 eventmask 中请求,它也会由
poll.poll()/poll.ipoll()报告,并且将其作为输入 eventmask 传入是无效的。
类¶
- class select.poll¶
创建一个轮询对象,它维护一组已注册的流(或任何暴露流协议的对象),并高效地等待,直到其中一个或多个变为可读、可写或发出异常状况信号。
用
register()添加流,用unregister()移除流,并且可用modify()更改要监视的事件集。配置完成后,调用poll()进行阻塞,直到有内容就绪(或超时到期),或调用ipoll()获取一个无需分配内存的基于迭代器的变体。- register(obj: Any, eventmask: int = select.POLLIN | select.POLLOUT) None¶
注册 流 obj 以进行轮询,监视由 eventmask(以下各项的逻辑或)给定的事件:
select.POLLIN-- 有可读取的数据select.POLLOUT-- 流可以接受更多要写入的数据
eventmask 默认为
select.POLLIN | select.POLLOUT。select.POLLHUP和select.POLLERR在输入 eventmask 中无效——它们是非请求事件,无论是否被请求,都会由poll()/ipoll()报告(这与 POSIX 语义一致)。对同一个 obj 多次调用此方法是允许的:后续调用会更新 obj 的事件掩码,其行为类似于
modify()。
- modify(obj: Any, eventmask: int) None¶
将一个已注册的 obj 的事件掩码更改为 eventmask。如果 obj 未注册,则引发带有
errno.ENOENT的OSError。
- poll(timeout: int = -1, /) List[Tuple]¶
阻塞,直到至少一个已注册的流准备就绪或发出异常状况信号,然后返回触发的流的列表。
timeout 是最大等待时间,以毫秒为单位。如果省略或为
-1,则调用无限期阻塞;0表示立即返回(非阻塞轮询)。返回一个
(obj, event, ...)元组的列表,每个触发的流对应一个。obj是已注册的流,event是发生的select.POLLIN/select.POLLOUT/select.POLLERR/select.POLLHUP标志的按位或。每个元组可能包含额外的、由实现定义的元素,因此不要假设其长度恰好为 2。如果 timeout 已过但没有任何对象就绪,则返回一个空列表。select.POLLHUP和select.POLLERR可能在任何时候返回(即使未被请求),并且必须加以处理——通常是注销并关闭受影响的流——否则后续调用将持续立即返回,并为该流设置这些标志。任何待处理的已调度回调都保证在进入轮询循环之前运行。
与 CPython 的差异
如上所述,返回的元组可能包含超过 2 个元素。
- ipoll(timeout: int = -1, flags: int = 0, /) Iterator[Tuple]¶
与
poll()类似,但不构建列表,而是返回一个迭代器,每次产生一个(obj, event, ...)元组。这避免了在每次调用时分配内存,这对于异步 I/O 调度器非常重要。产生的元组归被调用方所有:它会在下一次迭代时被复用(覆盖),因此必须在循环体内消费其内容,并且不得存储对它的引用。
timeout 的含义与
poll()相同。如果 flags 为1,则使用单次(one-shot)行为:事件已触发的流会自动清除其事件掩码(等效于poll.modify(obj, 0)),因此在用modify()再次设置其掩码之前,不会再为其报告任何事件。任何待处理的已调度回调都保证在进入轮询循环之前运行。
与 CPython 的差异
此方法是 MicroPython 的扩展。