select
— 等待 I/O 完成¶
此模块提供了对大多数操作系统中可用的 select()
和 poll()
函数、Solaris 及其衍生产品上可用的 devpoll()
、Linux 2.5+ 上可用的 epoll()
和大多数 BSD 上可用的 kqueue()
函数的访问。请注意,在 Windows 上,它仅适用于套接字;在其他操作系统上,它也适用于其他文件类型(特别是在 Unix 上,它适用于管道)。它不能用于常规文件来确定文件自上次读取以来是否已增长。
可用性:非 WASI。
此模块在 WebAssembly 上不起作用或不可用。有关更多信息,请参阅 WebAssembly 平台。
该模块定义了以下内容
- select.devpoll()¶
(仅在 Solaris 及其衍生产品上受支持。)返回一个
/dev/poll
轮询对象;有关 devpoll 对象支持的方法,请参阅下面的 /dev/poll 轮询对象 部分。devpoll()
对象与实例化时允许的文件描述符数量相关联。如果您的程序减少此值,devpoll()
将失败。如果您的程序增加此值,devpoll()
可能会返回不完整的活动文件描述符列表。新的文件描述符是不可继承的。
在 3.3 版本加入。
3.4 版本发生变更: 新的文件描述符现在是不可继承的。
- select.epoll(sizehint=-1, flags=0)¶
(仅在 Linux 2.5.44 及更高版本上受支持。)返回一个边缘轮询对象,该对象可用作 I/O 事件的边缘或水平触发接口。
sizehint 通知 epoll 预期的注册事件数量。它必须是正数,或者
-1
以使用默认值。它仅在不支持epoll_create1()
的旧系统上使用;否则它没有效果(尽管其值仍会被检查)。flags 已被弃用并完全忽略。但是,如果提供,其值必须为
0
或select.EPOLL_CLOEXEC
,否则会引发OSError
。有关 epolling 对象支持的方法,请参阅下面的 边缘和水平触发轮询 (epoll) 对象 部分。
epoll
对象支持上下文管理协议:当在with
语句中使用时,新的文件描述符会在块结束时自动关闭。新的文件描述符是不可继承的。
3.3 版本发生变更: 添加了 flags 参数。
3.4 版本发生变更: 添加了对
with
语句的支持。新的文件描述符现在是不可继承的。自 3.4 版本起已弃用: flags 参数。现在默认使用
select.EPOLL_CLOEXEC
。使用os.set_inheritable()
使文件描述符可继承。
- select.kqueue()¶
(仅在 BSD 上受支持。)返回一个内核队列对象;有关 kqueue 对象支持的方法,请参阅下面的 Kqueue 对象 部分。
新的文件描述符是不可继承的。
3.4 版本发生变更: 新的文件描述符现在是不可继承的。
- select.kevent(ident, filter=KQ_FILTER_READ, flags=KQ_EV_ADD, fflags=0, data=0, udata=0)¶
(仅在 BSD 上受支持。)返回一个内核事件对象;有关 kevent 对象支持的方法,请参阅下面的 Kevent 对象 部分。
- select.select(rlist, wlist, xlist[, timeout])¶
这是一个直接的 Unix
select()
系统调用接口。前三个参数是“可等待对象”的可迭代对象:可以是表示文件描述符的整数,也可以是具有名为fileno()
的无参数方法并返回此类整数的对象rlist: 等待直到可读
wlist: 等待直到可写
xlist: 等待“异常情况”(请参阅手册页,了解您的系统认为什么是此类情况)
允许空的可迭代对象,但接受三个空的可迭代对象是平台相关的。(已知在 Unix 上有效,但在 Windows 上无效。)可选的 timeout 参数指定以秒为单位的浮点数超时时间。当省略 timeout 参数时,函数会阻塞,直到至少有一个文件描述符准备就绪。超时值为零表示轮询,永不阻塞。
返回值是一个包含就绪对象的列表元组:前三个参数的子集。当达到超时时间而没有文件描述符就绪时,返回三个空列表。
可迭代对象中可接受的对象类型包括 Python 文件对象(例如
sys.stdin
,或由open()
或os.popen()
返回的对象),由socket.socket()
返回的套接字对象。您也可以自己定义一个 包装器 类,只要它有一个合适的fileno()
方法(该方法确实返回一个文件描述符,而不仅仅是一个随机整数)。备注
Windows 上的文件对象不可接受,但套接字可以。在 Windows 上,底层的
select()
函数由 WinSock 库提供,不处理非源自 WinSock 的文件描述符。3.5 版本发生变更: 当被信号中断时,函数现在会使用重新计算的超时时间重试,除非信号处理程序引发异常(请参阅 PEP 475 以了解其原理),而不是引发
InterruptedError
。
- select.PIPE_BUF¶
当管道被
select()
、poll()
或此模块中的其他接口报告为可写时,可以无阻塞地写入管道的最小字节数。这不适用于其他类型的文件类对象,例如套接字。POSIX 保证此值至少为 512。
可用性: Unix
在 3.2 版本加入。
/dev/poll
轮询对象¶
Solaris 及其衍生产品具有 /dev/poll
。虽然 select()
是 O(最高文件描述符),poll()
是 O(文件描述符数量),但 /dev/poll
是 O(活动文件描述符)。
/dev/poll
的行为与标准 poll()
对象非常接近。
- devpoll.close()¶
关闭轮询对象的文件描述符。
在 3.4 版本加入。
- devpoll.closed¶
如果轮询对象已关闭,则为
True
。在 3.4 版本加入。
- devpoll.fileno()¶
返回轮询对象的文件描述符编号。
在 3.4 版本加入。
- devpoll.register(fd[, eventmask])¶
向轮询对象注册一个文件描述符。未来的
poll()
方法调用将检查文件描述符是否有任何待处理的 I/O 事件。fd 可以是整数,也可以是具有返回整数的fileno()
方法的对象。文件对象实现了fileno()
,因此它们也可以用作参数。eventmask 是一个可选的位掩码,描述您要检查的事件类型。常量与
poll()
对象相同。默认值是常量POLLIN
、POLLPRI
和POLLOUT
的组合。警告
注册一个已注册的文件描述符不是错误,但结果未定义。适当的操作是先注销或修改它。这是与
poll()
相比的一个重要区别。
- devpoll.modify(fd[, eventmask])¶
此方法执行
unregister()
,然后执行register()
。它比显式执行相同的操作效率更高(一点点)。
- devpoll.unregister(fd)¶
从轮询对象中移除正在跟踪的文件描述符。与
register()
方法一样,fd 可以是整数,也可以是具有返回整数的fileno()
方法的对象。尝试移除从未注册的文件描述符会被安全地忽略。
- devpoll.poll([timeout])¶
轮询一组已注册的文件描述符,并返回一个可能为空的列表,其中包含具有事件或错误的描述符的
(fd, event)
2 元组。fd 是文件描述符,event 是一个位掩码,其中位设置为该描述符报告的事件 —POLLIN
表示等待输入,POLLOUT
表示描述符可写入,依此类推。空列表表示调用超时,没有文件描述符有任何事件要报告。如果给出 timeout,它指定系统在返回之前等待事件的毫秒数。如果省略 timeout、为 -1 或None
,则调用将阻塞,直到此轮询对象有事件发生。3.5 版本发生变更: 当被信号中断时,函数现在会使用重新计算的超时时间重试,除非信号处理程序引发异常(请参阅 PEP 475 以了解其原理),而不是引发
InterruptedError
。
边缘和水平触发轮询 (epoll) 对象¶
https://linux.die.net/man/4/epoll
eventmask
常量
含义
EPOLLIN
可读
EPOLLOUT
可写
EPOLLPRI
有紧急数据可读
EPOLLERR
关联文件描述符上发生错误情况
EPOLLHUP
关联文件描述符上发生挂起
EPOLLET
设置边缘触发行为,默认为水平触发行为
EPOLLONESHOT
设置单次行为。在拉出一个事件后,fd 在内部被禁用
EPOLLEXCLUSIVE
当关联的 fd 有事件时,只唤醒一个 epoll 对象。默认(如果未设置此标志)是唤醒所有轮询 fd 的 epoll 对象。
EPOLLRDHUP
流套接字对端关闭连接或关闭连接的写入半部分。
EPOLLRDNORM
等同于
EPOLLIN
EPOLLRDBAND
优先级数据带可读。
EPOLLWRNORM
等同于
EPOLLOUT
EPOLLWRBAND
优先级数据可写入。
EPOLLMSG
忽略。
EPOLLWAKEUP
防止在事件等待期间休眠。
3.6 版本新增: 添加了
EPOLLEXCLUSIVE
。它仅受 Linux 内核 4.5 或更高版本支持。3.14 版本新增: 添加了
EPOLLWAKEUP
。它仅受 Linux 内核 3.5 或更高版本支持。
- epoll.close()¶
关闭 epoll 对象的控制文件描述符。
- epoll.closed¶
如果 epoll 对象已关闭,则为
True
。
- epoll.fileno()¶
返回控制文件描述符的文件描述符编号。
- epoll.fromfd(fd)¶
从给定的文件描述符创建 epoll 对象。
- epoll.register(fd[, eventmask])¶
向 epoll 对象注册一个 fd 描述符。
- epoll.modify(fd, eventmask)¶
修改已注册的文件描述符。
- epoll.poll(timeout=None, maxevents=-1)¶
等待事件。超时时间以秒为单位(浮点数)。
3.5 版本发生变更: 当被信号中断时,函数现在会使用重新计算的超时时间重试,除非信号处理程序引发异常(请参阅 PEP 475 以了解其原理),而不是引发
InterruptedError
。
轮询对象¶
在大多数 Unix 系统上受支持的 poll()
系统调用为同时服务大量客户端的网络服务器提供了更好的可伸缩性。poll()
具有更好的可伸缩性,因为系统调用只需要列出感兴趣的文件描述符,而 select()
构建一个位图,为感兴趣的 fd 打开位,然后必须再次线性扫描整个位图。select()
是 O(最高文件描述符),而 poll()
是 O(文件描述符数量)。
- poll.register(fd[, eventmask])¶
向轮询对象注册一个文件描述符。未来的
poll()
方法调用将检查文件描述符是否有任何待处理的 I/O 事件。fd 可以是整数,也可以是具有返回整数的fileno()
方法的对象。文件对象实现了fileno()
,因此它们也可以用作参数。eventmask 是一个可选的位掩码,描述您要检查的事件类型,可以是下表中描述的常量
POLLIN
、POLLPRI
和POLLOUT
的组合。如果未指定,将使用默认值检查所有 3 种类型的事件。常量
含义
POLLIN
有数据可读
POLLPRI
有紧急数据可读
POLLOUT
准备输出:写入不会阻塞
POLLERR
某种错误情况
POLLHUP
挂起
POLLRDHUP
流套接字对端关闭连接,或关闭连接的写入半部分
POLLNVAL
无效请求:描述符未打开
注册已注册的文件描述符不是错误,并且与仅注册一次描述符具有相同的效果。
- poll.modify(fd, eventmask)¶
修改已注册的 fd。这与
register(fd, eventmask)
具有相同的效果。尝试修改从未注册的文件描述符会引发带有 errnoENOENT
的OSError
异常。
- poll.unregister(fd)¶
从轮询对象中移除正在跟踪的文件描述符。与
register()
方法一样,fd 可以是整数,也可以是具有返回整数的fileno()
方法的对象。尝试移除从未注册的文件描述符会导致引发
KeyError
异常。
- poll.poll([timeout])¶
轮询一组已注册的文件描述符,并返回一个可能为空的列表,其中包含具有事件或错误的描述符的
(fd, event)
2 元组。fd 是文件描述符,event 是一个位掩码,其中位设置为该描述符报告的事件 —POLLIN
表示等待输入,POLLOUT
表示描述符可写入,依此类推。空列表表示调用超时,没有文件描述符有任何事件要报告。如果给出 timeout,它指定系统在返回之前等待事件的毫秒数。如果省略 timeout、为负数或None
,则调用将阻塞,直到此轮询对象有事件发生。3.5 版本发生变更: 当被信号中断时,函数现在会使用重新计算的超时时间重试,除非信号处理程序引发异常(请参阅 PEP 475 以了解其原理),而不是引发
InterruptedError
。
Kqueue 对象¶
- kqueue.close()¶
关闭 kqueue 对象的控制文件描述符。
- kqueue.closed¶
如果 kqueue 对象已关闭,则为
True
。
- kqueue.fileno()¶
返回控制文件描述符的文件描述符编号。
- kqueue.fromfd(fd)¶
从给定的文件描述符创建 kqueue 对象。
- kqueue.control(changelist, max_events[, timeout]) eventlist ¶
kevent 的低级接口
changelist 必须是 kevent 对象的可迭代对象或
None
max_events 必须是 0 或正整数
超时时间以秒为单位(可能为浮点数);默认值为
None
,表示永远等待
3.5 版本发生变更: 当被信号中断时,函数现在会使用重新计算的超时时间重试,除非信号处理程序引发异常(请参阅 PEP 475 以了解其原理),而不是引发
InterruptedError
。
Kevent 对象¶
https://man.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
- kevent.filter¶
内核过滤器的名称。
常量
含义
KQ_FILTER_READ
接收描述符并在有数据可读时返回
KQ_FILTER_WRITE
接收描述符并在有数据可写时返回
KQ_FILTER_AIO
AIO 请求
KQ_FILTER_VNODE
当 fflag 中请求的一个或多个事件发生时返回
KQ_FILTER_PROC
监视进程 ID 上的事件
KQ_FILTER_NETDEV
监视网络设备上的事件 [在 macOS 上不可用]
KQ_FILTER_SIGNAL
每当监视的信号传递到进程时返回
KQ_FILTER_TIMER
建立任意定时器
- kevent.flags¶
过滤动作。
常量
含义
KQ_EV_ADD
添加或修改事件
KQ_EV_DELETE
从队列中移除事件
KQ_EV_ENABLE
允许control()返回事件
KQ_EV_DISABLE
禁用事件
KQ_EV_ONESHOT
首次发生后移除事件
KQ_EV_CLEAR
检索事件后重置状态
KQ_EV_SYSFLAGS
内部事件
KQ_EV_FLAG1
内部事件
KQ_EV_EOF
过滤器特定的 EOF 条件
KQ_EV_ERROR
参见返回值
- kevent.fflags¶
过滤器特定标志。
KQ_FILTER_READ
和KQ_FILTER_WRITE
过滤器标志常量
含义
KQ_NOTE_LOWAT
套接字缓冲区的低水位标记
KQ_FILTER_VNODE
过滤器标志常量
含义
KQ_NOTE_DELETE
调用了 unlink()
KQ_NOTE_WRITE
发生写入
KQ_NOTE_EXTEND
文件已扩展
KQ_NOTE_ATTRIB
属性已更改
KQ_NOTE_LINK
链接计数已更改
KQ_NOTE_RENAME
文件已重命名
KQ_NOTE_REVOKE
文件访问被撤销
KQ_FILTER_PROC
过滤器标志常量
含义
KQ_NOTE_EXIT
进程已退出
KQ_NOTE_FORK
进程已调用 fork()
KQ_NOTE_EXEC
进程已执行新进程
KQ_NOTE_PCTRLMASK
内部过滤器标志
KQ_NOTE_PDATAMASK
内部过滤器标志
KQ_NOTE_TRACK
在 fork() 之后跟踪进程
KQ_NOTE_CHILD
在子进程上返回 NOTE_TRACK
KQ_NOTE_TRACKERR
无法附加到子进程
KQ_FILTER_NETDEV
过滤器标志(在 macOS 上不可用)常量
含义
KQ_NOTE_LINKUP
链接已启动
KQ_NOTE_LINKDOWN
链接已关闭
KQ_NOTE_LINKINV
链接状态无效
- kevent.data¶
过滤器特定数据。
- kevent.udata¶
用户定义值。