select
--- 等待 I/O 完成?
該模塊提供了對 select()
和 poll()
函數的訪(fǎng)問(wèn),這些函數在大多數操作系統中是可用的。在 Solaris 及其衍生版本上可用 devpoll()
,在 Linux 2.5+ 上可用 epoll()
,在大多數 BSD 上可用 kqueue()
。注意,在 Windows 上,本模塊僅適用于套接字;在其他操作系統上,本模塊也適用于其他文件類(lèi)型(特別地,在 Unix 上也適用于管道)。本模塊不能用于常規文件,不能檢測出(自上次讀取文件后)文件是否有新數據寫(xiě)入。
備注
selectors
模塊是在 select
模塊原型的基礎上進(jìn)行高級且高效的 I/O 復用。推薦用戶(hù)改用 selectors
模塊,除非用戶(hù)希望對 OS 級的函數原型進(jìn)行精確控制。
該模塊定義以下內容:
- select.devpoll()?
(僅支持 Solaris 及其衍生版本)返回一個(gè)
/dev/poll
輪詢(xún)對象,請參閱下方 /dev/poll 輪詢(xún)對象 獲取 devpoll 對象所支持的方法。devpoll()
對象與實(shí)例化時(shí)允許的文件描述符數量有關(guān),如果在程序中降低了此數值,devpoll()
調用將失敗。如果程序提高了此數值,devpoll()
可能會(huì )返回一個(gè)不完整的活動(dòng)文件描述符列表。新的文件描述符是 不可繼承的。
3.3 新版功能.
在 3.4 版更改: 新的文件描述符現在是不可繼承的。
- select.epoll(sizehint=- 1, flags=0)?
(僅支持 Linux 2.5.44 或更高版本)返回一個(gè) edge poll 對象,該對象可作為 I/O 事件的邊緣觸發(fā)或水平觸發(fā)接口。
sizehint 指示 epoll 預計需要注冊的事件數。它必須為正數,或為 -1 以使用默認值。它僅在
epoll_create1()
不可用的舊系統上會(huì )被用到,其他情況下它沒(méi)有任何作用(盡管仍會(huì )檢查其值)。flags 已經(jīng)棄用且完全被忽略。但是,如果提供該值,則它必須是
0
或select.EPOLL_CLOEXEC
,否則會(huì )拋出OSError
異常。請參閱下方 邊緣觸發(fā)和水平觸發(fā)的輪詢(xún) (epoll) 對象 獲取 epoll 對象所支持的方法。
epoll
對象支持上下文管理器:當在with
語(yǔ)句中使用時(shí),新建的文件描述符會(huì )在運行至語(yǔ)句塊結束時(shí)自動(dòng)關(guān)閉。新的文件描述符是 不可繼承的。
在 3.3 版更改: 增加了 flags 參數。
在 3.4 版更改: 增加了對
with
語(yǔ)句的支持。新的文件描述符現在是不可繼承的。3.4 版后已移除: flags 參數?,F在默認采用
select.EPOLL_CLOEXEC
標志。使用os.set_inheritable()
來(lái)讓文件描述符可繼承。
- select.poll()?
(部分操作系統不支持)返回一個(gè) poll 對象,該對象支持注冊和注銷(xiāo)文件描述符,支持對描述符進(jìn)行輪詢(xún)以獲取 I/O 事件。請參閱下方 Poll 對象 獲取 poll 對象所支持的方法。
- select.kqueue()?
(僅支持 BSD)返回一個(gè)內核隊列對象,請參閱下方 Kqueue 對象 獲取 kqueue 對象所支持的方法。
新的文件描述符是 不可繼承的。
在 3.4 版更改: 新的文件描述符現在是不可繼承的。
- select.kevent(ident, filter=KQ_FILTER_READ, flags=KQ_EV_ADD, fflags=0, data=0, udata=0)?
(僅支持 BSD)返回一個(gè)內核事件對象,請參閱下方 Kevent 對象 獲取 kevent 對象所支持的方法。
- select.select(rlist, wlist, xlist[, timeout])?
這是一個(gè)明白直觀(guān)的 Unix
select()
系統調用接口。 前三個(gè)參數是由‘可等待對象’組成的序列:可以是代表文件描述符的整數,或是帶有名為fileno()
的返回這樣的整數的無(wú)形參方法的對象:rlist:等待,直到可以開(kāi)始讀取
wlist:等待,直到可以開(kāi)始寫(xiě)入
xlist:等待“異常情況”(請參閱當前系統的手冊,以獲取哪些情況稱(chēng)為異常情況)
允許空的可迭代對象,但是否接受三個(gè)空的可迭代對象則取決于具體平臺。 (已知在 Unix 上可行但在 Windows 上不可行。) 可選的 timeout 參數以一個(gè)浮點(diǎn)數表示超時(shí)秒數。 當省略 timeout 參數時(shí)該函數將阻塞直到至少有一個(gè)文件描述符準備就緒。 超時(shí)值為零表示執行輪詢(xún)且永不阻塞。
返回值是三個(gè)列表,包含已就緒對象,返回的三個(gè)列表是前三個(gè)參數的子集。當超時(shí)時(shí)間已到且沒(méi)有文件描述符就緒時(shí),返回三個(gè)空列表。
可迭代對象中可接受的對象類(lèi)型有 Python 文件對象 (例如
sys.stdin
以及open()
或os.popen()
所返回的對象),由socket.socket()
返回的套接字對象等。 你也可以自定義一個(gè) wrapper 類(lèi),只要它具有適當的fileno()
方法(該方法要確實(shí)返回一個(gè)文件描述符,而不能只是一個(gè)隨機整數)。備注
Windows 上不接受文件對象,但接受套接字。在 Windows 上,底層的
select()
函數由 WinSock 庫提供,且不處理不是源自 WinSock 的文件描述符。在 3.5 版更改: 現在,當本函數被信號中斷時(shí),重試超時(shí)將從頭開(kāi)始計時(shí),不會(huì )拋出
InterruptedError
異常。除非信號處理程序拋出異常(相關(guān)原理請參閱 PEP 475)。
- select.PIPE_BUF?
當一個(gè)管道已經(jīng)被
select()
、poll()
或本模塊中的某個(gè)接口報告為可寫(xiě)入時(shí),可以在不阻塞該管道的情況下寫(xiě)入的最小字節數。它不適用于套接字等其他類(lèi)型的文件類(lèi)對象。POSIX 上須保證該值不小于 512。
可用性: Unix
3.2 新版功能.
/dev/poll
輪詢(xún)對象?
Solaris 及其衍生版本具備 /dev/poll
。select()
復雜度為 O(最高文件描述符),poll()
為 O(文件描述符數量),而 /dev/poll
為 O(活動(dòng)的文件描述符)。
/dev/poll
的行為與標準 poll()
對象十分類(lèi)似。
- devpoll.close()?
關(guān)閉輪詢(xún)對象的文件描述符。
3.4 新版功能.
- devpoll.closed?
如果輪詢(xún)對象已關(guān)閉,則返回
True
。3.4 新版功能.
- devpoll.fileno()?
返回輪詢(xún)對象的文件描述符對應的數字。
3.4 新版功能.
- devpoll.register(fd[, eventmask])?
在輪詢(xún)對象中注冊文件描述符。這樣,將來(lái)調用
poll()
方法時(shí)將檢查文件描述符是否有未處理的 I/O 事件。fd 可以是整數,也可以是帶有fileno()
方法的對象(該方法返回一個(gè)整數)。文件對象已經(jīng)實(shí)現了fileno()
,因此它們也可以用作參數。eventmask 是可選的位掩碼,用于指定要檢查的事件類(lèi)型。這些常量與
poll()
對象所用的相同。本參數的默認值是常量POLLIN
、POLLPRI
和POLLOUT
的組合。警告
注冊已注冊過(guò)的文件描述符不會(huì )報錯,但是結果是不確定的。正確的操作是先注銷(xiāo)或直接修改它。與
poll()
相比,這是一個(gè)重要的區別。
- devpoll.modify(fd[, eventmask])?
此方法先執行
unregister()
后執行register()
。直接執行此操作效率(稍微)高一些。
- devpoll.unregister(fd)?
刪除輪詢(xún)對象正在跟蹤的某個(gè)文件描述符。與
register()
方法類(lèi)似,fd 可以是整數,也可以是帶有fileno()
方法的對象(該方法返回一個(gè)整數)。嘗試刪除從未注冊過(guò)的文件描述符將被安全地忽略。
- devpoll.poll([timeout])?
輪詢(xún)已注冊的文件描述符的集合,并返回一個(gè)列表,列表可能為空,也可能有多個(gè)
(fd, event)
二元組,其中包含了要報告事件或錯誤的描述符。fd 是文件描述符,event 是一個(gè)位掩碼,表示該描述符所報告的事件 ---POLLIN
表示可以讀取,POLLOUT
表示該描述符可以寫(xiě)入,依此類(lèi)推??樟斜肀硎菊{用超時(shí),沒(méi)有任何文件描述符報告事件。如果指定了 timeout,它將指定系統等待事件時(shí),等待多長(cháng)時(shí)間后返回(以毫秒為單位)。如果 timeout 為空,-1 或None
,則本調用將阻塞,直到輪詢(xún)對象發(fā)生事件為止。在 3.5 版更改: 現在,當本函數被信號中斷時(shí),重試超時(shí)將從頭開(kāi)始計時(shí),不會(huì )拋出
InterruptedError
異常。除非信號處理程序拋出異常(相關(guān)原理請參閱 PEP 475)。
邊緣觸發(fā)和水平觸發(fā)的輪詢(xún) (epoll) 對象?
https://linux.die.net/man/4/epoll
eventmask
常量
含意
EPOLLIN
可讀
EPOLLOUT
可寫(xiě)
EPOLLPRI
緊急數據讀取
EPOLLERR
在關(guān)聯(lián)的文件描述符上有錯誤情況發(fā)生
EPOLLHUP
關(guān)聯(lián)的文件描述符已掛起
EPOLLET
設置觸發(fā)方式為邊緣觸發(fā),默認為水平觸發(fā)
EPOLLONESHOT
設置 one-shot 模式。觸發(fā)一次事件后,該描述符會(huì )在輪詢(xún)對象內部被禁用。
EPOLLEXCLUSIVE
當已關(guān)聯(lián)的描述符發(fā)生事件時(shí),僅喚醒一個(gè) epoll 對象。默認(如果未設置此標志)是喚醒所有輪詢(xún)該描述符的 epoll 對象。
EPOLLRDHUP
流套接字的對側關(guān)閉了連接或關(guān)閉了寫(xiě)入到一半的連接。
EPOLLRDNORM
等同于
EPOLLIN
EPOLLRDBAND
可以讀取優(yōu)先數據帶。
EPOLLWRNORM
等同于
EPOLLOUT
EPOLLWRBAND
可以寫(xiě)入優(yōu)先級數據。
EPOLLMSG
忽略
3.6 新版功能: 增加了
EPOLLEXCLUSIVE
。僅支持 Linux Kernel 4.5 或更高版本。
- epoll.close()?
關(guān)閉用于控制 epoll 對象的文件描述符。
- epoll.closed?
如果 epoll 對象已關(guān)閉,則返回
True
。
- epoll.fileno()?
返回文件描述符對應的數字,該描述符用于控制 epoll 對象。
- epoll.fromfd(fd)?
根據給定的文件描述符創(chuàng )建 epoll 對象。
- epoll.register(fd[, eventmask])?
在 epoll 對象中注冊一個(gè)文件描述符。
- epoll.modify(fd, eventmask)?
修改一個(gè)已注冊的文件描述符。
- epoll.poll(timeout=None, maxevents=- 1)?
等待事件發(fā)生,timeout 是浮點(diǎn)數,單位為秒。
在 3.5 版更改: 現在,當本函數被信號中斷時(shí),重試超時(shí)將從頭開(kāi)始計時(shí),不會(huì )拋出
InterruptedError
異常。除非信號處理程序拋出異常(相關(guān)原理請參閱 PEP 475)。
Poll 對象?
大多數 Unix 系統支持 poll()
系統調用,為服務(wù)器提供了更好的可伸縮性,使服務(wù)器可以同時(shí)服務(wù)于大量客戶(hù)端。poll()
的伸縮性更好,因為該調用內部?jì)H列出所關(guān)注的文件描述符,而 select()
會(huì )構造一個(gè) bitmap,在其中將所關(guān)注的描述符所對應的 bit 打開(kāi),然后重新遍歷整個(gè) bitmap。因此 select()
復雜度是 O(最高文件描述符),而 poll()
是 O(文件描述符數量)。
- poll.register(fd[, eventmask])?
在輪詢(xún)對象中注冊文件描述符。這樣,將來(lái)調用
poll()
方法時(shí)將檢查文件描述符是否有未處理的 I/O 事件。fd 可以是整數,也可以是帶有fileno()
方法的對象(該方法返回一個(gè)整數)。文件對象已經(jīng)實(shí)現了fileno()
,因此它們也可以用作參數。eventmask 是可選的位掩碼,用于指定要檢查的事件類(lèi)型,它可以是常量
POLLIN
、POLLPRI
和POLLOUT
的組合,如下表所述。如果未指定本參數,默認將會(huì )檢查所有 3 種類(lèi)型的事件。常量
含意
POLLIN
有要讀取的數據
POLLPRI
有緊急數據需要讀取
POLLOUT
準備輸出:寫(xiě)不會(huì )阻塞
POLLERR
某種錯誤條件
POLLHUP
掛起
POLLRDHUP
流套接字的對側關(guān)閉了連接,或關(guān)閉了寫(xiě)入到一半的連接
POLLNVAL
無(wú)效的請求:描述符未打開(kāi)
注冊已注冊過(guò)的文件描述符不會(huì )報錯,且等同于只注冊一次該描述符。
- poll.modify(fd, eventmask)?
修改一個(gè)已注冊的文件描述符,等同于
register(fd, eventmask)
。嘗試修改未注冊的文件描述符會(huì )拋出OSError
異常,錯誤碼為ENOENT
。
- poll.unregister(fd)?
刪除輪詢(xún)對象正在跟蹤的某個(gè)文件描述符。與
register()
方法類(lèi)似,fd 可以是整數,也可以是帶有fileno()
方法的對象(該方法返回一個(gè)整數)。嘗試刪除從未注冊過(guò)的文件描述符會(huì )拋出
KeyError
異常。
- poll.poll([timeout])?
輪詢(xún)已注冊的文件描述符的集合,并返回一個(gè)列表,列表可能為空,也可能有多個(gè)
(fd, event)
二元組,其中包含了要報告事件或錯誤的描述符。fd 是文件描述符,event 是一個(gè)位掩碼,表示該描述符所報告的事件 ---POLLIN
表示可以讀取,POLLOUT
表示該描述符可以寫(xiě)入,依此類(lèi)推??樟斜肀硎菊{用超時(shí),沒(méi)有任何文件描述符報告事件。如果指定了 timeout,它將指定系統等待事件時(shí),等待多長(cháng)時(shí)間后返回(以毫秒為單位)。如果 timeout 為空、負數 或None
,則本調用將阻塞,直到輪詢(xún)對象發(fā)生事件為止。在 3.5 版更改: 現在,當本函數被信號中斷時(shí),重試超時(shí)將從頭開(kāi)始計時(shí),不會(huì )拋出
InterruptedError
異常。除非信號處理程序拋出異常(相關(guān)原理請參閱 PEP 475)。
Kqueue 對象?
- kqueue.close()?
關(guān)閉用于控制 kqueue 對象的文件描述符。
- kqueue.closed?
如果 kqueue 對象已關(guān)閉,則返回
True
。
- kqueue.fileno()?
返回文件描述符對應的數字,該描述符用于控制 epoll 對象。
- kqueue.fromfd(fd)?
根據給定的文件描述符創(chuàng )建 kqueue 對象。
- kqueue.control(changelist, max_events[, timeout]) eventlist ?
Kevent 的低級接口
changelist 必須是一個(gè)可迭代對象,迭代出 kevent 對象,否則置為
None
。max_events 必須是 0 或一個(gè)正整數。
timeout 單位為秒(一般為浮點(diǎn)數),默認為
None
,即永不超時(shí)。
在 3.5 版更改: 現在,當本函數被信號中斷時(shí),重試超時(shí)將從頭開(kāi)始計時(shí),不會(huì )拋出
InterruptedError
異常。除非信號處理程序拋出異常(相關(guān)原理請參閱 PEP 475)。
Kevent 對象?
https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
- kevent.filter?
內核篩選器的名稱(chēng)。
常量
含意
KQ_FILTER_READ
獲取描述符,并在有數據可讀時(shí)返回
KQ_FILTER_WRITE
獲取描述符,并在有數據可寫(xiě)時(shí)返回
KQ_FILTER_AIO
AIO 請求
KQ_FILTER_VNODE
當在 fflag 中監視的一個(gè)或多個(gè)請求事件發(fā)生時(shí)返回
KQ_FILTER_PROC
監視進(jìn)程ID上的事件
KQ_FILTER_NETDEV
Watch for events on a network device [not available on macOS]
KQ_FILTER_SIGNAL
每當監視的信號傳遞到進(jìn)程時(shí)返回
KQ_FILTER_TIMER
建立一個(gè)任意的計時(shí)器
- kevent.flags?
篩選器操作。
常量
含意
KQ_EV_ADD
添加或修改事件
KQ_EV_DELETE
從隊列中刪除事件
KQ_EV_ENABLE
Permitscontrol() 返回事件
KQ_EV_DISABLE
禁用事件
KQ_EV_ONESHOT
在第一次發(fā)生后刪除事件
KQ_EV_CLEAR
檢索事件后重置狀態(tài)
KQ_EV_SYSFLAGS
內部事件
KQ_EV_FLAG1
內部事件
KQ_EV_EOF
篩選特定EOF條件
KQ_EV_ERROR
請參閱返回值
- kevent.fflags?
篩選特定標志。
KQ_FILTER_READ
和KQ_FILTER_WRITE
篩選標志:常量
含意
KQ_NOTE_LOWAT
套接字緩沖區的低水線(xiàn)
KQ_FILTER_VNODE
篩選標志:常量
含意
KQ_NOTE_DELETE
已調用 unlink()
KQ_NOTE_WRITE
發(fā)生寫(xiě)入
KQ_NOTE_EXTEND
文件已擴展
KQ_NOTE_ATTRIB
屬性已更改
KQ_NOTE_LINK
鏈接計數已更改
KQ_NOTE_RENAME
文件已重命名
KQ_NOTE_REVOKE
對文件的訪(fǎng)問(wèn)權限已被撤銷(xiāo)
KQ_FILTER_PROC
filter flags:常量
含意
KQ_NOTE_EXIT
進(jìn)程已退出
KQ_NOTE_FORK
該進(jìn)程調用了 fork()
KQ_NOTE_EXEC
進(jìn)程已執行新進(jìn)程
KQ_NOTE_PCTRLMASK
內部篩選器標志
KQ_NOTE_PDATAMASK
內部篩選器標志
KQ_NOTE_TRACK
跨 fork() 執行進(jìn)程
KQ_NOTE_CHILD
在 NOTE_TRACK 的子進(jìn)程上返回
KQ_NOTE_TRACKERR
無(wú)法附加到子對象
KQ_FILTER_NETDEV
filter flags (not available on macOS):常量
含意
KQ_NOTE_LINKUP
鏈接已建立
KQ_NOTE_LINKDOWN
鏈接已斷開(kāi)
KQ_NOTE_LINKINV
鏈接狀態(tài)無(wú)效
- kevent.data?
篩選特定數據。
- kevent.udata?
用戶(hù)自定義值。