select — 等待 I/O 完成


此模組提供了對大多數作業系統中可用的 select()poll() 函式、Solaris 及其衍生產品上可用的 devpoll()、Linux 2.5+ 上可用的 epoll() 和大多數 BSD 上可用的 kqueue() 函式的訪問。請注意,在 Windows 上,它僅適用於套接字;在其他作業系統上,它也適用於其他檔案型別(特別是在 Unix 上,它適用於管道)。它不能用於常規檔案來確定檔案自上次讀取以來是否已增長。

備註

selectors 模組提供了高階高效的 I/O 多路複用,它構建於 select 模組的原語之上。除非使用者需要精確控制所使用的作業系統級別原語,否則建議使用 selectors 模組。

可用性:非 WASI。

此模組在 WebAssembly 上不起作用或不可用。有關更多資訊,請參閱 WebAssembly 平臺

該模組定義了以下內容

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 物件支援的方法,請參閱下面的 邊緣和水平觸發輪詢 (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/pollO(活動檔案描述符)。

/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

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.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) 具有相同的效果。嘗試修改從未註冊的檔案描述符會引發帶有 errno ENOENTOSError 異常。

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

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

使用者定義值。