选择—awaitI/O 完成


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

Note

selectors模块允许在select模块 Primitives 的基础上进行高层且高效的 I/O 复用。鼓励用户改用selectors模块,除非他们希望对使用的 OS 级 Primitives 进行精确控制。

该模块定义以下内容:

  • exception select. error

在版本 3.3 中进行了更改:在 PEP 3151之后,该类被命名为OSError

  • select. devpoll ( )
    • (仅在 Solaris 和衍生产品上受支持.)返回/dev/poll轮询对象;否则,返回 0.有关 devpoll 对象支持的方法,请参见下面的/ dev/poll 轮询对象部分。

devpoll()对象链接到实例化时允许的文件 Descriptors 数量。如果您的程序减小此值,则devpoll()将失败。如果您的程序增加此值,则devpoll()可能会返回不完整的活动文件 Descriptors 列表。

新文件 Descriptors 为non-inheritable

版本 3.3 中的新Function。

在版本 3.4 中进行了更改:现在不可继承新文件 Descriptors。

  • select. epoll(* sizehint = -1 flags = 0 *)
    • (仅在 Linux 2.5.44 和更高版本上受支持.)返回边缘轮询对象,该对象可用作 I/O 事件的边缘或级别触发接口。
  • sizehint *通知 epoll 预期要注册的事件数。它必须为正数,或为-1 以使用默认值。它仅在epoll_create1()不可用的旧系统上使用;否则,它没有任何作用(尽管仍会检查其值)。

  • flags *已弃用,并被完全忽略。但是,提供时,其值必须为0select.EPOLL_CLOEXEC,否则将提高OSError

有关轮询对象支持的方法,请参见下面的边缘和水平触发轮询(epoll)对象部分。

epoll对象支持上下文 Management 协议:在with语句中使用时,新文件 Descriptors 在块末自动关闭。

新文件 Descriptors 为non-inheritable

在版本 3.3 中进行了更改:添加了* flags *参数。

在版本 3.4 中更改:添加了对with语句的支持。现在,新的文件 Descriptors 是不可继承的。

从 3.4 版开始不推荐使用:* flags *参数。现在默认使用select.EPOLL_CLOEXEC。使用os.set_inheritable()使文件 Descriptors 可继承。

  • select. poll ( )

    • (并非所有 os 都支持.)返回一个轮询对象,该对象支持注册和注销文件 Descriptors,然后对它们进行轮询以获取 I/O 事件;有关轮询对象支持的方法,请参见下面的Polling Objects部分。
  • select. kqueue ( )

    • (仅在 BSD 上受支持.)返回内核队列对象;否则为 false。有关 kqueue 对象支持的方法,请参见下面的Kqueue Objects部分。

新文件 Descriptors 为non-inheritable

在版本 3.4 中进行了更改:现在不可继承新文件 Descriptors。

  • select. kevent(* ident filter = KQ_FILTER_READ flags = KQ_EV_ADD fflags = 0 data = 0 udata = 0 *)

    • (仅在 BSD 上受支持.)返回内核事件对象;否则为 false。有关 kevent 对象支持的方法,请参见下面的Kevent Objects部分。
  • select. select(* rlist wlist xlist * [,* timeout *])

    • 这是 Unix select()系统调用的直接接口。前三个参数是“await 对象”的可迭代对象:代表文件 Descriptors 的整数或具有名为fileno()的无参数方法的对象返回这样的整数:
    • rlist *:等到准备好阅读
    • wlist *:等到准备好写
    • xlist *:await“异常情况”(有关系统认为这种情况的信息,请参见手册页)

允许使用空的 Iterable,但是接受三个空的 Iterable 取决于平台。 (众所周知,它可以在 Unix 上工作,但不能在 Windows 上工作.)可选的* timeout 参数将超时指定为以秒为单位的浮点数。如果Ellipsis timeout *参数,该Function将阻塞直到至少一个文件 Descriptors 准备就绪。超时值为零表示轮询且永不阻塞。

返回值是准备好的对象列表的三倍:前三个参数的子集。在没有准备好文件 Descriptors 的情况下达到超时时,将返回三个空列表。

可迭代对象中可接受的对象类型包括 Python file objects(例如sys.stdinopen()os.popen()返回的对象),socket.socket()返回的套接字对象。您也可以自己定义* wrapper *类,只要它具有适当的fileno()方法(该方法实际上返回文件 Descriptors,而不仅仅是返回随机整数)即可。

Note

Windows 上的文件对象是不可接受的,但套接字是可接受的。在 Windows 上,基础select()函数由 WinSock 库提供,并且不处理不是源自 WinSock 的文件 Descriptors。

在版本 3.5 中进行了更改:现在,当 signal break时,函数将重新计算超时重试,除非 signal 处理程序引发异常(基本原理请参见 PEP 475),而不是引发InterruptedError

  • select. PIPE_BUF
    • 当管道已被select()poll()或此模块中的另一个接口报告为可写入时,可以在不阻塞管道的情况下写入的最小字节数。这不适用于套接字等其他类型的文件状对象。

POSIX 保证此值至少为 512.

Availability: Unix

3.2 版中的新Function。

/dev/poll 轮询对象

Solaris 及其派生类具有/dev/pollselect()是 O(最高文件 Descriptors),poll()是 O(文件 Descriptors 数量),而/dev/poll是 O(活动文件 Descriptors)。

/dev/poll行为与标准poll()对象非常接近。

  • devpoll. close ( )
    • 关闭轮询对象的文件 Descriptors。

3.4 版的新Function。

  • devpoll. closed
    • True如果关闭了轮询对象。

3.4 版的新Function。

  • devpoll. fileno ( )
    • 返回轮询对象的文件 Descriptors 号。

3.4 版的新Function。

  • devpoll. register(* fd * [,* eventmask *])
    • 向轮询对象注册文件 Descriptors。然后,将来对poll()方法的调用将检查文件 Descriptors 是否具有任何未决的 I/O 事件。 * fd *可以是整数,也可以是具有返回整数的fileno()方法的对象。文件对象实现fileno(),因此它们也可用作参数。
  • eventmask *是可选的位掩码,用于描述您要检查的事件的类型。常量与poll()对象相同。默认值为常数POLLINPOLLPRIPOLLOUT的组合。

Warning

注册已经注册的文件 Descriptors 不是错误,但是结果是不确定的。适当的操作是先注销或修改它。与poll()相比,这是一个重要的区别。

  • devpoll. modify(* fd * [,* eventmask *])

  • devpoll. unregister(* fd *)

    • 删除轮询对象正在跟踪的文件 Descriptors。就像register()方法一样,* fd *可以是整数,也可以是具有fileno()方法的对象返回整数。

try删除从未注册过的文件 Descriptors 将被安全地忽略。

  • devpoll. poll([* timeout *])
    • 轮询已注册文件 Descriptors 的集合,并返回一个可能为空的列表,其中包含要报告事件或错误的 Descriptors 的(fd, event) 2Tuples。 * fd 是文件 Descriptors,而 event 是位掩码,其中为该 Descriptors 的报告事件设置了位-POLLINawaitImporting,POLLOUT表示可以写入 Descriptors,依此类推。空列表表示呼叫超时,并且没有文件 Descriptors 报告任何事件。如果指定了 timeout ,则它指定系统将在返回之前 await 事件的时间长度(以毫秒为单位)。如果Ellipsis timeout *,-1 或None,则该调用将阻塞,直到该轮询对象发生事件为止。

在版本 3.5 中进行了更改:现在,当 signal break时,函数将重新计算超时重试,除非 signal 处理程序引发异常(基本原理请参见 PEP 475),而不是引发InterruptedError

边缘和水平触发轮询(epoll)对象

Note

https://linux.die.net/man/4/epoll

eventmask

ConstantMeaning
EPOLLIN可供阅读
EPOLLOUT可写
EPOLLPRI紧急数据读取
EPOLLERR错误状况发生在 assoc 上。 fd
EPOLLHUP挂断发生在 assoc 上。 fd
EPOLLET设置边缘触发行为,默认为电平触发行为
EPOLLONESHOT设置单发行为。撤消一个事件后,内部将禁用 fd
EPOLLEXCLUSIVE当关联的 fd 发生事件时,仅唤醒一个 epoll 对象。默认(如果未设置此标志)是唤醒所有在 fd 上轮询的 epoll 对象。
EPOLLRDHUP流套接字对等方关闭连接或关闭写入一半连接。
EPOLLRDNORM相当于EPOLLIN
EPOLLRDBAND可以读取优先数据带。
EPOLLWRNORM相当于EPOLLOUT
EPOLLWRBAND可以写入优先级数据。
EPOLLMSGIgnored.

3.6 版的新Function:EPOLLEXCLUSIVE已添加。仅 Linux Kernel 4.5 或更高版本支持。

  • epoll. close ( )

    • 关闭 epoll 对象的控制文件 Descriptors。
  • epoll. closed

    • True如果 epoll 对象已关闭。
  • epoll. fileno ( )

    • 返回控件 fd 的文件 Descriptors 号。
  • epoll. fromfd(* fd *)

    • 从给定的文件 Descriptors 中创建一个 epoll 对象。
  • epoll. register(* fd * [,* eventmask *])

    • 向 epoll 对象注册 fdDescriptors。
  • epoll. modify(* fd eventmask *)

    • 修改注册文件 Descriptors。
  • epoll. unregister(* fd *)

    • 从 epoll 对象中删除注册的文件 Descriptors。
  • epoll. poll(* timeout = None maxevents = -1 *)

    • await 事件。超时(以秒为单位)(Float)

在版本 3.5 中进行了更改:现在,当 signal break时,函数将重新计算超时重试,除非 signal 处理程序引发异常(基本原理请参见 PEP 475),而不是引发InterruptedError

Polling Objects

大多数 Unix 系统上支持的poll()系统调用为同时服务于许多 Client 端的 Web Service 器提供了更好的可伸缩性。 poll()具有更好的伸缩性,因为系统调用仅需要列出感兴趣的文件 Descriptors,而select()会构建位图,为感兴趣的 fds 打开位,然后再重新线性扫描整个位图。 select()是 O(最高文件 Descriptors),而poll()是 O(最高文件 Descriptors 数量)。

  • poll. register(* fd * [,* eventmask *])
    • 向轮询对象注册文件 Descriptors。然后,将来对poll()方法的调用将检查文件 Descriptors 是否具有任何未决的 I/O 事件。 * fd *可以是整数,也可以是具有返回整数的fileno()方法的对象。文件对象实现fileno(),因此它们也可用作参数。
  • eventmask *是可选的位掩码,用于描述您要检查的事件的类型,并且可以是下表中描述的常量POLLINPOLLPRIPOLLOUT的组合。如果未指定,则使用的默认值将检查所有 3 种类型的事件。
ConstantMeaning
POLLIN有要读取的数据
POLLPRI有紧急数据需要阅读
POLLOUT准备输出:写不会阻塞
POLLERR某种错误情况
POLLHUPHung up
POLLRDHUP流套接字对等体关闭连接,或关闭写入一半连接
POLLNVAL无效的请求:Descriptors 未打开

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

  • poll. modify(* fd eventmask *)

    • 修改已注册的 fd。与register(fd, eventmask)具有相同的效果。try修改从未注册的文件 Descriptors 会导致OSError异常,出现 errno ENOENT
  • poll. unregister(* fd *)

    • 删除轮询对象正在跟踪的文件 Descriptors。就像register()方法一样,* fd *可以是整数,也可以是具有fileno()方法的对象返回整数。

try删除从未注册的文件 Descriptors 会引发KeyError异常。

  • poll. poll([* timeout *])
    • 轮询已注册文件 Descriptors 的集合,并返回一个可能为空的列表,其中包含要报告事件或错误的 Descriptors 的(fd, event) 2Tuples。 * fd 是文件 Descriptors,而 event 是位掩码,其中为该 Descriptors 的报告事件设置了位-POLLINawaitImporting,POLLOUT表示可以写入 Descriptors,依此类推。空列表表示呼叫超时,并且没有文件 Descriptors 报告任何事件。如果指定了 timeout ,则它指定系统将在返回之前 await 事件的时间长度(以毫秒为单位)。如果Ellipsis timeout *,negative 或None,则该调用将阻塞,直到该轮询对象发生事件为止。

在版本 3.5 中进行了更改:现在,当 signal break时,函数将重新计算超时重试,除非 signal 处理程序引发异常(基本原理请参见 PEP 475),而不是引发InterruptedError

Kqueue Objects

  • kqueue. close ( )

    • 关闭 kqueue 对象的控制文件 Descriptors。
  • kqueue. closed

    • True如果 kqueue 对象已关闭。
  • kqueue. fileno ( )

    • 返回控件 fd 的文件 Descriptors 号。
  • kqueue. fromfd(* fd *)

    • 从给定的文件 Descriptors 创建一个 kqueue 对象。
  • kqueue. control(* changelist max_events * [,* timeout *])→事件列表

    • kevent 的低级接口
  • 变更列表必须是 kevent 对象或None的可迭代对象

  • max_events 必须为 0 或正整数

  • 超时(以秒为单位)(可能会 Float);默认值为None,以永远 await

在版本 3.5 中进行了更改:现在,当 signal break时,函数将重新计算超时重试,除非 signal 处理程序引发异常(基本原理请参见 PEP 475),而不是引发InterruptedError

Kevent Objects

https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2

  • kevent. ident

    • 用于标识事件的值。解释取决于过滤器,但通常是文件 Descriptors。在构造函数中,ident 可以是 int 或具有fileno()方法的对象。 kevent 在内部存储整数。
  • kevent. filter

    • 内核过滤器的名称。
ConstantMeaning
KQ_FILTER_READ获取 Descriptors 并在有数据可读取时返回
KQ_FILTER_WRITE获取 Descriptors 并在有数据可写时返回
KQ_FILTER_AIOAIO requests
KQ_FILTER_VNODE返回在* fflag *中监视的一个或多个请求事件发生时返回
KQ_FILTER_PROC监视进程 ID 上的事件
KQ_FILTER_NETDEV监视网络设备上的事件[在 Mac OS X 上不可用]
KQ_FILTER_SIGNAL每当将观察到的 signal 传递到流程时返回
KQ_FILTER_TIMER构建一个任意计时器
  • kevent. flags
    • Filter action.
ConstantMeaning
KQ_EV_ADD添加或修改事件
KQ_EV_DELETE从队列中删除事件
KQ_EV_ENABLEPermitscontrol()返回事件
KQ_EV_DISABLEDisablesevent
KQ_EV_ONESHOT首次发生后删除事件
KQ_EV_CLEAR检索事件后重置状态
KQ_EV_SYSFLAGSinternal event
KQ_EV_FLAG1internal event
KQ_EV_EOF过滤特定的 EOF 条件
KQ_EV_ERROR查看返回值
  • kevent. fflags
    • 过滤特定标志。

KQ_FILTER_READKQ_FILTER_WRITE过滤器标志:

ConstantMeaning
KQ_NOTE_LOWAT套接字缓冲区的低水位线

KQ_FILTER_VNODE个过滤器标志:

ConstantMeaning
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个过滤器标志:

ConstantMeaning
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 上不可用):

ConstantMeaning
KQ_NOTE_LINKUP链接已构建
KQ_NOTE_LINKDOWN链接已断开
KQ_NOTE_LINKINV链接状态无效
  • kevent. data

    • 过滤特定数据。
  • kevent. udata

    • 用户定义的值。