select --- 等待一組串流上的事件¶
此模組提供函式,可有效率地等待直到一個或多個 串流(實作串流協定的類檔案物件,例如 socket、UART 以及其他 I/O 物件)就緒可進行讀取或寫入,而非在單一物件上忙碌等待或封鎖。
poll 物件是建議使用的介面:它可擴展至大量串流,且透過 poll.ipoll() 使用時不需配置記憶體。模組層級的 select() 函式則是效率較低的相容性介面。
使用 poll 物件的範例::
import select
poller = select.poll()
poller.register(uart, select.POLLIN)
while True:
# Wait up to 1000 ms for the UART to have data.
for obj, event in poller.poll(1000):
if event & select.POLLIN:
print(obj.read())
使用模組層級 select() 函式的範例::
import select
# Wait up to 1 second for the socket to become readable.
rlist, wlist, xlist = select.select([sock], [], [], 1.0)
if rlist:
data = sock.recv(100)
函式¶
- select.select(rlist: List, wlist: List, xlist: List, timeout: float | None = None) Tuple[List, List, List]¶
等待直到一個或多個給定的串流物件就緒,或直到 timeout 逾時。
rlist 是要監看其可讀性的物件清單。
wlist 是要監看其可寫性的物件清單。
xlist 是要監看其錯誤或斷線狀況的物件清單。
timeout 是最長等待時間,單位為秒(接受浮點數)。若省略或為
None,呼叫會無限期封鎖;0則立即回傳(非封鎖式輪詢)。
回傳一個由清單組成的 3 元組
(rlist, wlist, xlist)。每個回傳的清單分別是對應輸入清單的子集,包含已就緒可讀取、已就緒可寫入,或發出錯誤/斷線訊號的物件。若 timeout 過去而沒有任何項目就緒,則三個清單皆為空。
常數¶
- select.POLLERR: int¶
串流上發生了錯誤狀況。這是一個 非主動請求的 事件:即使未在 eventmask 中請求,
poll.poll()/poll.ipoll()也會回報它,且將它作為輸入 eventmask 傳入是無效的。
- select.POLLHUP: int¶
串流已斷線/中斷連線。這是一個 非主動請求的 事件:即使未在 eventmask 中請求,
poll.poll()/poll.ipoll()也會回報它,且將它作為輸入 eventmask 傳入是無效的。
類別¶
- class select.poll¶
建立一個輪詢物件,它維護一組已註冊的串流(或任何公開串流協定的物件),並有效率地等待直到其中一個或多個變為可讀、可寫,或發出例外狀況訊號。
串流以
register()加入、以unregister()移除,要監看的事件集可用modify()變更。設定完成後,呼叫poll()以封鎖直到有項目就緒(或逾時),或呼叫ipoll()取得不需配置記憶體、以迭代器為基礎的變體。- register(obj: Any, eventmask: int = select.POLLIN | select.POLLOUT) None¶
註冊 串流 obj 以進行輪詢,監看由 eventmask(下列各項的邏輯 OR)所指定的事件:
select.POLLIN-- 有資料可供讀取select.POLLOUT-- 串流可接受更多資料寫入
eventmask 預設為
select.POLLIN | select.POLLOUT。select.POLLHUP與select.POLLERR在輸入 eventmask 中是 無效的 -- 它們是非主動請求的事件,無論是否被請求,都會由poll()/ipoll()回報(這與 POSIX 語意一致)。對同一個 obj 多次呼叫此方法是可以的:後續呼叫會更新 obj 的事件遮罩,其行為如同
modify()。
- modify(obj: Any, eventmask: int) None¶
將一個已註冊的 obj 的事件遮罩變更為 eventmask。若 obj 未註冊,則引發帶有
errno.ENOENT的OSError。
- poll(timeout: int = -1, /) List[Tuple]¶
封鎖直到至少有一個已註冊串流就緒或發出例外狀況訊號,然後回傳已觸發的串流清單。
timeout 是最長等待時間,單位為 毫秒。若省略或為
-1,呼叫會無限期封鎖;0則立即回傳(非封鎖式輪詢)。回傳一個由
(obj, event, ...)元組組成的清單,每個觸發的串流對應一個。obj是已註冊的串流,event則是所發生的select.POLLIN/select.POLLOUT/select.POLLERR/select.POLLHUP旗標的位元 OR。每個元組可能包含額外的實作定義元素,因此請勿假設其長度恰為 2。若 timeout 過去而沒有任何項目就緒,則回傳一個空清單。select.POLLHUP與select.POLLERR可能在任何時候被回傳(即使未被請求),且必須加以處理 -- 通常是取消註冊並關閉受影響的串流 -- 否則後續呼叫會持續為該串流立即回傳並設定這些旗標。任何待處理的已排程回呼函式,保證會在進入輪詢迴圈之前執行。
與 CPython 的差異
如上所述,回傳的元組可能包含超過 2 個元素。
- ipoll(timeout: int = -1, flags: int = 0, /) Iterator[Tuple]¶
與
poll()類似,但它不會建立清單,而是回傳一個迭代器,每次產出一個(obj, event, ...)元組。這避免了每次呼叫時的記憶體配置,對非同步 I/O 排程器而言相當重要。所產出的元組為 被呼叫端所擁有:它會在下一次迭代時被重複使用(覆寫),因此其內容必須在迴圈主體內消耗完畢,且不得儲存對它的參考。
timeout 的意義與
poll()相同。若 flags 為1,則使用單次(one-shot)行為:事件已觸發的串流,其事件遮罩會自動被清除(等同於poll.modify(obj, 0)),因此在以modify()重新設定其遮罩之前,不會再為它回報任何事件。任何待處理的已排程回呼函式,保證會在進入輪詢迴圈之前執行。
與 CPython 的差異
此方法是 MicroPython 的擴充功能。