select
— 等待 I/O 完成¶
此模块提供对大多数操作系统中可用的 select()
和 poll()
函数的访问权限,在 Solaris 及其派生产品中可用的 devpoll()
,在 Linux 2.5+ 中可用的 epoll()
,以及在大多数 BSD 中可用的 kqueue()
。请注意,在 Windows 上,它仅适用于套接字;在其他操作系统上,它也适用于其他文件类型(特别是在 Unix 上,它适用于管道)。它不能用于常规文件来确定文件自上次读取后是否已增大。
可用性: 不支持 Emscripten,不支持 WASI。
此模块在 WebAssembly 平台 wasm32-emscripten
和 wasm32-wasi
上不起作用或不可用。有关详细信息,请参阅 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.poll()¶
(并非所有操作系统都支持。)返回一个轮询对象,该对象支持注册和取消注册文件描述符,然后轮询它们以查找 I/O 事件;有关轮询对象支持的方法,请参见下面的 轮询对象 部分。
- 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
关联的 fd 发生错误情况
EPOLLHUP
关联的 fd 发生挂起
EPOLLET
设置边缘触发行为,默认是级别触发行为
EPOLLONESHOT
设置一次性行为。在提取一个事件后,fd 在内部被禁用
EPOLLEXCLUSIVE
当关联的 fd 发生事件时,仅唤醒一个 epoll 对象。默认(如果未设置此标志)是唤醒轮询 fd 的所有 epoll 对象。
EPOLLRDHUP
流套接字对等方关闭连接或关闭连接的写一半
EPOLLRDNORM
等同于
EPOLLIN
EPOLLRDBAND
可以读取优先数据段
EPOLLWRNORM
等同于
EPOLLOUT
EPOLLWRBAND
可以写入优先数据
EPOLLMSG
忽略
3.6 版本中已添加: 已添加
EPOLLEXCLUSIVE
。它仅受 Linux Kernel 4.5 或更高版本支持。
- epoll.close()¶
关闭 epoll 对象的控制文件描述符。
- epoll.closed¶
如果 epoll 对象已关闭,则为
True
。
- epoll.fileno()¶
返回控制 fd 的文件描述符编号。
- epoll.fromfd(fd)¶
从给定的文件描述符创建 epoll 对象。
- epoll.register(fd[, eventmask])¶
使用 epoll 对象注册 fd 描述符。
- epoll.modify(fd, eventmask)¶
修改已注册的文件描述符。
- epoll.poll(timeout=None, maxevents=-1)¶
等待事件。timeout 以秒为单位(浮点数)
在版本 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)
的效果相同。尝试修改从未注册的文件描述符会导致OSError
异常,其中 errnoENOENT
被引发。
- poll.unregister(fd)¶
删除由轮询对象跟踪的文件描述符。就像
register()
方法一样,fd 可以是整数或具有fileno()
方法的对象,该方法返回一个整数。尝试删除从未注册的文件描述符会导致引发
KeyError
异常。
- poll.poll([timeout])¶
轮询注册的文件描述符集,并返回一个可能为空的列表,其中包含
(fd, event)
2 元组,用于具有事件或错误要报告的描述符。fd 是文件描述符,event 是一个位掩码,其中为该描述符报告的事件设置了位——POLLIN
表示等待输入,POLLOUT
表示可以写入描述符,依此类推。空列表表示调用超时,并且没有文件描述符有任何事件要报告。如果给出了 timeout,它指定系统在返回之前等待事件的时间长度(以毫秒为单位)。如果省略、为负数或None
,则该调用将阻塞,直到此轮询对象出现事件。在 3.5 版本中已更改: 现在,当被信号中断时,该函数将使用重新计算的超时重试,但信号处理程序引发异常时除外(有关基本原理,请参见 PEP 475),而不是引发
InterruptedError
。
Kqueue 对象¶
- kqueue.close()¶
关闭 kqueue 对象的控制文件描述符。
- kqueue.closed¶
True
,如果 kqueue 对象已关闭。
- kqueue.fileno()¶
返回控制 fd 的文件描述符编号。
- kqueue.fromfd(fd)¶
从给定的文件描述符创建一个 kqueue 对象。
- kqueue.control(changelist, max_events[, timeout]) eventlist ¶
kevent 的底层接口
changelist 必须是 kevent 对象或
None
的可迭代对象max_events 必须为 0 或正整数
timeout 以秒为单位(可以是浮点数);默认值为
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¶
特定于过滤器的 data。
- kevent.udata¶
用户定义值。