select — 等待 I/O 完成 — Python 文档

来自菜鸟教程
Python/docs/3.10/library/select
跳转至:导航、​搜索

select — 等待 I/O 完成


该模块提供对大多数操作系统中可用的 select()poll() 函数的访问,Solaris 及其衍生版本上可用的 devpoll(),Linux 2.5+ 和衍生版本上可用的 epoll() kqueue() 在大多数 BSD 上可用。 请注意,在 Windows 上,它仅适用于套接字; 在其他操作系统上,它也适用于其他文件类型(特别是在 Unix 上,它适用于管道)。 它不能用于常规文件以确定自上次读取以来文件是否已增长。

笔记

selectors 模块允许基于 select 模块原语的高级和高效 I/O 多路复用。 鼓励用户改用 选择器 模块,除非他们想要精确控制所使用的操作系统级原语。


该模块定义了以下内容:

exception select.error

OSError 的已弃用别名。

3.3 版本更改: PEP 3151 之后,该类被设为 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 已弃用并完全忽略。 但是,在提供时,其值必须为 0select.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。

3.2 版中的新功能。

/dev/poll 轮询对象

Solaris 和衍生产品有 /dev/pollselect() 是 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() 对象相同。 默认值是常量 POLLINPOLLPRIPOLLOUT 的组合。

警告

注册一个已经注册的文件描述符不是错误,但结果是未定义的。 适当的操作是先注销或修改它。 与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

事件掩码

持续的 意义
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
True 如果 epoll 对象关闭。
epoll.fileno()
返回控件 fd 的文件描述符编号。
epoll.fromfd(fd)
从给定的文件描述符创建一个 epoll 对象。
epoll.register(fd[, eventmask])
使用 epoll 对象注册 fd 描述符。
epoll.modify(fd, eventmask)
修改已注册的文件描述符。
epoll.unregister(fd)

从 epoll 对象中删除已注册的文件描述符。

3.9 版更改: 该方法不再忽略 EBADF 错误。

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 是一个可选的位掩码,描述要检查的事件类型,可以是常量 POLLINPOLLPRIPOLLOUT 的组合],见下表。 如果未指定,则使用的默认值将检查所有 3 种类型的事件。

持续的

意义

POLLIN

有数据要读取

POLLPRI

有紧急数据要读取

POLLOUT

准备输出:写入不会阻塞

POLLERR

某种错误条件

POLLHUP

挂了

POLLRDHUP

流套接字对等关闭连接,或关闭写入一半的连接

POLLNVAL

无效请求:描述符未打开

注册一个已经注册的文件描述符不是错误,并且与只注册一次描述符具有相同的效果。

poll.modify(fd, eventmask)
修改一个已经注册的 fd。 这与 register(fd, eventmask) 具有相同的效果。 尝试修改从未注册的文件描述符会导致 OSError 异常,并引发 errno ENOENT
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.close()
关闭 kqueue 对象的控制文件描述符。
kqueue.closed
True 如果 kqueue 对象关闭。
kqueue.fileno()
返回控件 fd 的文件描述符编号。
kqueue.fromfd(fd)
从给定的文件描述符创建一个 kqueue 对象。
kqueue.control(changelist, max_events[, timeout]) eventlist

kevent 的低级接口

  • 更改列表必须是 kevent 对象的可迭代对象或 None

  • max_events 必须为 0 或正整数

  • 以秒为单位的超时(可能浮动); 默认为 None,永远等待

在 3.5 版中更改:该函数现在在被信号中断时重试并重新计算超时,除非信号处理程序引发异常(请参阅 PEP 475理由),而不是提高 InterruptedError


凯文对象

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_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

Permitscontrol() 返回事件

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_READKQ_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
用户定义的值。