select --- Waiting for I/O 完成?
該模塊提供了對 select() 和 poll() 函數的訪問,這些函數在大多數操作系統中是可用的。在 Solaris 及其衍生版本上可用 devpoll(),在 Linux 2.5+ 上可用 epoll(),在大多數 BSD 上可用 kqueue()。注意,在 Windows 上,本模塊僅適用于套接字;在其他操作系統上,本模塊也適用于其他文件類型(特別地,在 Unix 上也適用于管道)。本模塊不能用于常規文件,不能檢測出(自上次讀取文件后)文件是否有新數據寫入。
該模塊定義以下內容:
-
select.devpoll()? (僅支持 Solaris 及其衍生版本)返回一個
/dev/poll輪詢對象,請參閱下方 /dev/poll 輪詢對象 獲取 devpoll 對象所支持的方法。devpoll()對象與實例化時允許的文件描述符數量有關,如果在程序中降低了此數值,devpoll()調用將失敗。如果程序提高了此數值,devpoll()可能會返回一個不完整的活動文件描述符列表。新的文件描述符 non-inheritable.
3.3 新版功能.
在 3.4 版更改: 新的文件描述符現在是不可繼承的。
-
select.epoll(sizehint=-1, flags=0)? (僅支持 Linux 2.5.44 或更高版本)返回一個輪詢對象,該對象可作為 I/O 事件的邊緣觸發或水平觸發接口。
sizehint 指示 epoll 預計需要注冊的事件數。它必須為正數,或為 -1 以使用默認值。它僅在
epoll_create1()不可用的舊系統上有用,其他情況下它沒有任何作用(盡管仍會檢查其值)。flags 已經棄用且完全被忽略。但是,如果提供該值,則它必須是
0或select.EPOLL_CLOEXEC,否則會拋出OSError異常。請參閱下方 邊緣觸發和水平觸發的輪詢 (epoll) 對象 獲取 epoll 對象所支持的方法。
epoll對象支持上下文管理器:當在with語句中使用時,新建的文件描述符會在運行至語句塊結束時自動銷毀。新的文件描述符 non-inheritable.
在 3.3 版更改: 增加了 flags 參數。
在 3.4 版更改: 增加了對
with語句的支持。新的文件描述符現在是不可繼承的。3.4 版后已移除: flags 參數。現在默認采用
select.EPOLL_CLOEXEC標志。使用os.set_inheritable()來讓文件描述符可繼承。
-
select.poll()? (部分操作系統不支持)返回一個輪詢對象,該對象支持注冊和注銷文件描述符,支持對描述符進行輪詢以獲取 I/O 事件。有關輪詢對象支持的方法,請參閱下方 Poll 對象 部分。
-
select.kqueue()? (僅支持 BSD)返回一個內核隊列對象,請參閱下方 Kqueue 對象 獲取 kqueue 對象所支持的方法。
新的文件描述符 non-inheritable.
在 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()返回的套接字對象等。 你也可以自定義一個 wrapper 類,只要它具有適當的fileno()方法(該方法要確實返回一個文件描述符,而不能只是一個隨機整數)。注解
Windows 上不接受文件對象,但接受套接字。在 Windows 上,底層的
select()函數由 WinSock 庫提供,且不處理不是源自 WinSock 的文件描述符。在 3.5 版更改: 現在,當本函數被信號中斷時,重試超時將從頭開始計時,不會拋出
InterruptedError異常。除非信號處理程序拋出異常(相關原理請參閱 PEP 475)。
-
select.PIPE_BUF? 當一個管道已經被
select()、poll()或本模塊中的某個接口報告為可寫入時,可以在不阻塞該管道的情況下寫入的最小字節數。它不適用于套接字等其他類型的文件類對象。POSIX 上須保證該值不小于 512。
可用性: Unix
3.2 新版功能.
/dev/poll 輪詢對象?
Solaris 及其衍生版本具備 /dev/poll。select() 復雜度為 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()對象所用的相同。本參數的默認值是常量POLLIN、POLLPRI和POLLOUT的組合。警告
注冊已注冊過的文件描述符不會報錯,但是結果是不確定的。正確的操作是先注銷或直接修改它。與
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 版更改: 現在,當本函數被信號中斷時,重試超時將從頭開始計時,不會拋出
InterruptedError異常。除非信號處理程序拋出異常(相關原理請參閱 PEP 475)。
邊緣觸發和水平觸發的輪詢 (epoll) 對象?
https://linux.die.net/man/4/epoll
屏蔽事件
常數
含義
EPOLLIN可讀
EPOLLOUT可寫
EPOLLPRI緊急數據讀取
EPOLLERR在關聯的文件描述符上有錯誤情況發生
EPOLLHUP關聯的文件描述符已掛起
EPOLLET設置觸發方式為邊緣觸發,默認為水平觸發
EPOLLONESHOT設置 one-shot 模式。觸發一次事件后,該描述符會在輪詢對象內部被禁用。
EPOLLEXCLUSIVE當已關聯的描述符發生事件時,僅喚醒一個 epoll 對象。默認(如果未設置此標志)是喚醒所有輪詢該描述符的 epoll 對象。
EPOLLRDHUP流套接字的對側關閉了連接或關閉了寫入到一半的連接。
EPOLLRDNORMEquivalent to
EPOLLIN
EPOLLRDBAND可以讀取優先數據帶。
EPOLLWRNORMEquivalent to
EPOLLOUT
EPOLLWRBAND可以寫入優先級數據。
EPOLLMSG忽略
3.6 新版功能: 增加了
EPOLLEXCLUSIVE。僅支持 Linux Kernel 4.5 或更高版本。
-
epoll.close()? 關閉用于控制 epoll 對象的那個文件描述符。
-
epoll.closed? 如果 epoll 對象已關閉,則返回
True。
-
epoll.fileno()? 返回用于控制 epoll 對象的文件描述符對應的數字。
-
epoll.fromfd(fd)? 根據給定的文件描述符創建 epoll 對象。
-
epoll.register(fd[, eventmask])? 在 epoll 對象中注冊一個文件描述符。
-
epoll.modify(fd, eventmask)? 修改一個已注冊的文件描述符。
-
epoll.unregister(fd)? 從 epoll 對象中刪除一個已注冊的文件描述符。
-
epoll.poll(timeout=-1, maxevents=-1)? 等待事件發生,timeout 是浮點數,單位為秒。
在 3.5 版更改: 現在,當本函數被信號中斷時,重試超時將從頭開始計時,不會拋出
InterruptedError異常。除非信號處理程序拋出異常(相關原理請參閱 PEP 475)。
Poll 對象?
大多數 Unix 系統支持 poll() 系統調用,為服務器提供了更好的可伸縮性,使服務器可以同時服務于大量客戶端。poll() 的伸縮性更好,因為該調用內部僅列出所關注的文件描述符,而 select() 會構造一個 bitmap,在其中將所關注的描述符所對應的 bit 打開,然后重新遍歷整個 bitmap。因此 select() 復雜度是 O(最高文件描述符),而 poll() 是 O(文件描述符數量)。
-
poll.register(fd[, eventmask])? 在輪詢對象中注冊文件描述符。這樣,將來調用
poll()方法時將檢查文件描述符是否有未處理的 I/O 事件。fd 可以是整數,也可以是帶有fileno()方法的對象(該方法返回一個整數)。文件對象已經實現了fileno(),因此它們也可以用作參數。eventmask 是可選的位掩碼,用于指定要檢查的事件類型,它可以是常量
POLLIN、POLLPRI和POLLOUT的組合,如下表所述。如果未指定本參數,默認將會檢查所有 3 種類型的事件。常數
含義
POLLIN有要讀取的數據
POLLPRI有緊急數據需要讀取
POLLOUT準備輸出:寫不會阻塞
POLLERR某種錯誤條件
POLLHUP掛起
POLLRDHUP流套接字對等體關閉連接,或關閉寫入一半連接
POLLNVAL無效的請求:描述符未打開
注冊已注冊過的文件描述符不會報錯,且等同于只注冊一次該描述符。
-
poll.modify(fd, eventmask)? 修改一個已注冊的文件描述符,等同于
register(fd, eventmask)。嘗試修改未注冊的文件描述符會拋出OSError異常,錯誤碼為ENOENT。
-
poll.unregister(fd)? 刪除輪詢對象正在跟蹤的某個文件描述符。與
register()方法類似,fd 可以是整數,也可以是帶有fileno()方法的對象(該方法返回一個整數)。嘗試刪除從未注冊過的文件描述符會拋出
KeyError異常。
-
poll.poll([timeout])? 輪詢已注冊的文件描述符的集合,并返回一個列表,列表可能為空,也可能有多個
(fd, event)二元組,其中包含了要報告事件或錯誤的描述符。fd 是文件描述符,event 是一個位掩碼,表示該描述符所報告的事件 ---POLLIN表示可以讀取,POLLOUT表示該描述符可以寫入,依此類推。空列表表示調用超時,沒有任何文件描述符報告事件。如果指定了 timeout,它將指定系統等待事件時,等待多長時間后返回(以毫秒為單位)。如果 timeout 為空、負數 或None,則本調用將阻塞,直到輪詢對象發生事件為止。在 3.5 版更改: 現在,當本函數被信號中斷時,重試超時將從頭開始計時,不會拋出
InterruptedError異常。除非信號處理程序拋出異常(相關原理請參閱 PEP 475)。
Kqueue 對象?
-
kqueue.close()? 關閉用于控制 kqueue 對象的文件描述符。
-
kqueue.closed? 如果 kqueue 對象已關閉,則返回
True。
-
kqueue.fileno()? 返回用于控制 epoll 對象的文件描述符對應的數字。
-
kqueue.fromfd(fd)? 根據給定的文件描述符創建 kqueue 對象。
-
kqueue.control(changelist, max_events[, timeout]) → eventlist? Kevent 的低級接口
changelist 必須是一個可迭代對象,迭代出 kevent 對象,否則置為
None。max_events 必須是 0 或一個正整數。
timeout 單位為秒(一般為浮點數),默認為
None,即永不超時。
在 3.5 版更改: 現在,當本函數被信號中斷時,重試超時將從頭開始計時,不會拋出
InterruptedError異常。除非信號處理程序拋出異常(相關原理請參閱 PEP 475)。
Kevent 對象?
https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
-
kevent.filter? 內核過濾器的名稱。
常數
含義
KQ_FILTER_READ獲取描述符,并在有數據可讀時返回
KQ_FILTER_WRITE獲取描述符,并在有數據可寫時返回
KQ_FILTER_AIOAIO 請求
KQ_FILTER_VNODE當在 fflag 中監視的一個或多個請求事件發生時返回
KQ_FILTER_PROC監視進程ID上的事件
KQ_FILTER_NETDEV觀察網絡設備上的事件[在Mac OS X上不可用]
KQ_FILTER_SIGNAL每當監視的信號傳遞到進程時返回
KQ_FILTER_TIMER建立一個任意的計時器
-
kevent.flags? 篩選器操作。
常數
含義
KQ_EV_ADD添加或修改事件
KQ_EV_DELETE從隊列中刪除事件
KQ_EV_ENABLEPermitscontrol() 返回事件
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_READ和KQ_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_PROCfilter flags:常數
含義
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上不可用):常數
含義
KQ_NOTE_LINKUP鏈接已建立
KQ_NOTE_LINKDOWN鏈接已斷開
KQ_NOTE_LINKINV鏈接狀態無效
-
kevent.data? 過濾特定數據。
-
kevent.udata? 用戶定義的值。
