selectors
— 高階 I/O 多路複用¶
在 3.4 版本加入。
原始碼: Lib/selectors.py
引言¶
此模組基於 select
模組原語構建,允許進行高階且高效的 I/O 多路複用。除非使用者希望對所使用的作業系統級原語進行精確控制,否則建議使用此模組。
它定義了一個抽象基類 BaseSelector
,以及幾種具體實現(KqueueSelector
、EpollSelector
…),可用於等待多個檔案物件的 I/O 就緒通知。在下文中,“檔案物件”指任何具有 fileno()
方法的物件,或原始檔案描述符。參見 檔案物件。
DefaultSelector
是當前平臺上最有效實現的別名:這應該是大多數使用者的預設選擇。
備註
支援的檔案物件型別取決於平臺:在 Windows 上,支援套接字,但不支援管道;而在 Unix 上,兩者都支援(可能還支援其他一些型別,例如 FIFO 或特殊檔案裝置)。
參見
select
低階 I/O 多路複用模組。
可用性:非 WASI。
此模組在 WebAssembly 上不起作用或不可用。有關更多資訊,請參閱 WebAssembly 平臺。
類¶
類層次結構
BaseSelector
+-- SelectSelector
+-- PollSelector
+-- EpollSelector
+-- DevpollSelector
+-- KqueueSelector
在下文中,events 是一個位掩碼,表示應在給定檔案物件上等待哪些 I/O 事件。它可以是以下模組常量的組合
- class selectors.SelectorKey¶
SelectorKey
是一個namedtuple
,用於將檔案物件與其底層檔案描述符、選定的事件掩碼和附加資料關聯起來。它由幾個BaseSelector
方法返回。- fileobj¶
已註冊的檔案物件。
- fd¶
底層檔案描述符。
- events¶
必須在此檔案物件上等待的事件。
- data¶
與此檔案物件關聯的可選不透明資料:例如,這可以用於儲存每個客戶端的會話 ID。
- class selectors.BaseSelector¶
BaseSelector
用於等待多個檔案物件上的 I/O 事件就緒。它支援檔案流注冊、登出,以及等待這些流上的 I/O 事件的方法,並帶有一個可選的超時。它是一個抽象基類,因此不能被例項化。請改用DefaultSelector
,或者如果您想專門使用某個實現,並且您的平臺支援它,則可以使用SelectSelector
、KqueueSelector
等。BaseSelector
及其具體實現支援 上下文管理器 協議。- abstractmethod register(fileobj, events, data=None)¶
註冊檔案物件以進行選擇,監控其 I/O 事件。
fileobj 是要監控的檔案物件。它可以是整數檔案描述符,也可以是具有
fileno()
方法的物件。events 是要監控的事件的位掩碼。data 是一個不透明物件。這會返回一個新的
SelectorKey
例項,或者在事件掩碼或檔案描述符無效時引發ValueError
,或者在檔案物件已註冊時引發KeyError
。
- abstractmethod unregister(fileobj)¶
從選擇中登出檔案物件,將其從監控中移除。檔案物件應在關閉之前登出。
fileobj 必須是先前已註冊的檔案物件。
這會返回關聯的
SelectorKey
例項,或者在 fileobj 未註冊時引發KeyError
。如果 fileobj 無效(例如,它沒有fileno()
方法或其fileno()
方法返回無效值),它將引發ValueError
。
- modify(fileobj, events, data=None)¶
更改已註冊檔案物件的受監控事件或附加資料。
這等同於
BaseSelector.unregister(fileobj)
後跟BaseSelector.register(fileobj, events, data)
,但可以更高效地實現。這會返回一個新的
SelectorKey
例項,或者在事件掩碼或檔案描述符無效時引發ValueError
,或者在檔案物件未註冊時引發KeyError
。
- abstractmethod select(timeout=None)¶
等待直到某些已註冊的檔案物件變為就緒,或超時過期。
如果
timeout > 0
,這指定了最長等待時間,以秒為單位。如果timeout <= 0
,呼叫將不會阻塞,並將報告當前就緒的檔案物件。如果 timeout 為None
,呼叫將阻塞直到受監控的檔案物件變為就緒。這會返回一個
(key, events)
元組列表,每個就緒檔案物件對應一個。key 是與就緒檔案物件對應的
SelectorKey
例項。events 是此檔案物件上就緒事件的位掩碼。備註
如果當前程序接收到訊號,此方法可能會在任何檔案物件變為就緒或超時過去之前返回:在這種情況下,將返回一個空列表。
3.5 版中變更: 如果訊號處理器沒有引發異常,當被訊號中斷時,選擇器現在會重新計算超時並重試(參見 PEP 475 以瞭解原理),而不是在超時前返回空事件列表。
- close()¶
關閉選擇器。
必須呼叫此方法以確保釋放任何底層資源。選擇器一旦關閉就不應再使用。
- get_key(fileobj)¶
返回與已註冊檔案物件關聯的鍵。
這會返回與此檔案物件關聯的
SelectorKey
例項,或者在檔案物件未註冊時引發KeyError
。
- abstractmethod get_map()¶
返回檔案物件到選擇器鍵的對映。
這會返回一個
Mapping
例項,將已註冊的檔案物件對映到其關聯的SelectorKey
例項。
- class selectors.DefaultSelector¶
預設選擇器類,使用當前平臺上最有效的實現。這應該是大多數使用者的預設選擇。
- class selectors.SelectSelector¶
基於
select.select()
的選擇器。
- class selectors.PollSelector¶
基於
select.poll()
的選擇器。
- class selectors.EpollSelector¶
基於
select.epoll()
的選擇器。- fileno()¶
這會返回底層
select.epoll()
物件使用的檔案描述符。
- class selectors.DevpollSelector¶
基於
select.devpoll()
的選擇器。- fileno()¶
這會返回底層
select.devpoll()
物件使用的檔案描述符。
在 3.5 版本加入。
- class selectors.KqueueSelector¶
基於
select.kqueue()
的選擇器。- fileno()¶
這會返回底層
select.kqueue()
物件使用的檔案描述符。
示例¶
這是一個簡單的 echo 伺服器實現
import selectors
import socket
sel = selectors.DefaultSelector()
def accept(sock, mask):
conn, addr = sock.accept() # Should be ready
print('accepted', conn, 'from', addr)
conn.setblocking(False)
sel.register(conn, selectors.EVENT_READ, read)
def read(conn, mask):
data = conn.recv(1000) # Should be ready
if data:
print('echoing', repr(data), 'to', conn)
conn.send(data) # Hope it won't block
else:
print('closing', conn)
sel.unregister(conn)
conn.close()
sock = socket.socket()
sock.bind(('localhost', 1234))
sock.listen(100)
sock.setblocking(False)
sel.register(sock, selectors.EVENT_READ, accept)
while True:
events = sel.select()
for key, mask in events:
callback = key.data
callback(key.fileobj, mask)