18.3. select — 等待 I/O 完成 — Python 文档
18.3. 选择 — 等待 I/O 完成
该模块提供对大多数操作系统中可用的 select() 和 poll() 函数的访问,Solaris 及其衍生版本上可用的 devpoll(),Linux 2.5+ 和衍生版本上可用的 epoll() kqueue() 在大多数 BSD 上可用。 请注意,在 Windows 上,它仅适用于套接字; 在其他操作系统上,它也适用于其他文件类型(特别是在 Unix 上,它适用于管道)。 它不能用于常规文件以确定自上次读取以来文件是否已增长。
该模块定义了以下内容:
- exception select.error
OSError 的已弃用别名。
- 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 对象支持的方法,请参阅下面的 Edge 和 Level Trigger Polling (epoll) Objects 部分。
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 file objects(例如
sys.stdin,或 open() 或 os.popen()) 返回的对象,socket.socket() 返回的套接字对象。 你也可以自己定义一个 wrapper 类,只要它有一个合适的 fileno() 方法(真正返回一个文件描述符,而不仅仅是一个随机整数)。笔记
Windows 上的文件对象是不可接受的,但套接字是。 在 Windows 上,底层的
select()函数由 WinSock 库提供,并且不处理不是源自 WinSock 的文件描述符。在 3.5 版中更改:该函数现在在被信号中断时重试并重新计算超时,除非信号处理程序引发异常(请参阅 PEP 475理由),而不是提高 InterruptedError。
- select.PIPE_BUF
当管道已被 select()、poll() 或此模块中的其他接口报告为可以写入时,可以在不阻塞的情况下写入管道的最小字节数. 这不适用于其他类型的类文件对象,例如套接字。
POSIX 保证该值至少为 512。 可用性:Unix。
3.2 版中的新功能。
18.3.1. /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。
18.3.2. 边缘和电平触发轮询 (epoll) 对象
http://linux.die.net/man/4/epoll
事件掩码
持续的 意义 EPOLLIN可供阅读 EPOLLOUT可写 EPOLLPRI需要读取的紧急数据 EPOLLERR关联上发生错误情况。 FD EPOLLHUP挂断发生在协会上。 FD EPOLLET设置边沿触发行为,默认为电平触发行为 EPOLLONESHOT设置一次性行为。 一个事件被拉出后,fd在内部被禁用 EPOLLEXCLUSIVE当关联的 fd 有事件时,只唤醒一个 epoll 对象。 默认(如果未设置此标志)是唤醒所有在 fd 上轮询的 epoll 对象。 EPOLLRDHUP流套接字对等端关闭连接或关闭写入一半的连接。 EPOLLRDNORM相当于 EPOLLINEPOLLRDBAND可以读取优先数据带。 EPOLLWRNORM相当于 EPOLLOUTEPOLLWRBAND可以写入优先数据。 EPOLLMSG忽略。
- epoll.close()
- 关闭 epoll 对象的控制文件描述符。
- epoll.closed
True如果 epoll 对象关闭。
- epoll.fileno()
- 返回控件 fd 的文件描述符编号。
- epoll.fromfd(fd)
- 从给定的文件描述符创建一个 epoll 对象。
- epoll.register(fd[, eventmask])
- 使用 epoll 对象注册 fd 描述符。
- epoll.modify(fd, eventmask)
- 修改已注册的文件描述符。
- epoll.unregister(fd)
- 从 epoll 对象中删除已注册的文件描述符。
- epoll.poll(timeout=- 1, maxevents=- 1)
等待事件。 以秒为单位的超时(浮动)
在 3.5 版中更改:该函数现在在被信号中断时重试并重新计算超时,除非信号处理程序引发异常(请参阅 PEP 475理由),而不是提高 InterruptedError。
18.3.3. 轮询对象
大多数 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,它指定系统在返回之前等待事件的时间长度(以毫秒为单位)。 如果 timeout 被省略、否定或 None,调用将阻塞,直到此轮询对象有事件。在 3.5 版中更改:该函数现在在被信号中断时重试并重新计算超时,除非信号处理程序引发异常(请参阅 PEP 475理由),而不是提高 InterruptedError。
18.3.4. 队列对象
- kqueue.close()
- 关闭 kqueue 对象的控制文件描述符。
- kqueue.closed
True如果 kqueue 对象关闭。
- kqueue.fileno()
- 返回控件 fd 的文件描述符编号。
- kqueue.fromfd(fd)
- 从给定的文件描述符创建一个 kqueue 对象。
- kqueue.control(changelist, max_events[, timeout=None]) eventlist
kevent 的低级接口
更改列表必须是 kevent 对象或
None的可迭代对象max_events 必须为 0 或正整数
以秒为单位的超时(可能浮动)
在 3.5 版中更改:该函数现在在被信号中断时重试并重新计算超时,除非信号处理程序引发异常(请参阅 PEP 475理由),而不是提高 InterruptedError。
18.3.5. 凯文对象
https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
- kevent.ident
- 用于标识事件的值。 解释取决于过滤器,但通常是文件描述符。 在构造函数中,ident 可以是 int 或具有 fileno() 方法的对象。 kevent 在内部存储整数。
- kevent.filter
内核过滤器的名称。
持续的
意义
KQ_FILTER_READ获取一个描述符并在有数据可供读取时返回
KQ_FILTER_WRITE获取一个描述符并在有数据可写时返回
KQ_FILTER_AIOAIO 请求
KQ_FILTER_VNODE当在 fflag 中观察到的一个或多个请求事件发生时返回
KQ_FILTER_PROC监视进程 ID 上的事件
KQ_FILTER_NETDEV监视网络设备上的事件 [在 Mac OS X 上不可用]
KQ_FILTER_SIGNAL每当监视的信号传递给进程时返回
KQ_FILTER_TIMER建立一个任意定时器
- kevent.flags
过滤动作。
持续的
意义
KQ_EV_ADD添加或修改事件
KQ_EV_DELETE从队列中移除一个事件
KQ_EV_ENABLEPermitscontrol() 返回事件
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_DELETEunlink() 被调用
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过滤器标志(在 Mac OS X 上不可用):持续的
意义
KQ_NOTE_LINKUP链接已建立
KQ_NOTE_LINKDOWN链接已关闭
KQ_NOTE_LINKINV链接状态无效
- kevent.data
- 过滤特定数据。
- kevent.udata
- 用户定义的值。