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 輪詢物件;請參閱下面的/dev/poll 輪詢物件部分,瞭解 devpoll 物件支援的方法。

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) 二元組,表示具有要報告的事件或錯誤的檔案描述符。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 物件註冊一個檔案描述符。

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 物件

kqueue.close()

關閉 kqueue 物件的控制檔案描述符。

kqueue.closed

如果 kqueue 物件已關閉,則為 True

kqueue.fileno()

返回控制 fd 的檔案描述符編號。

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

使用者定義的值。