selectors — 高階 I/O 多路複用

3.4 版本新增。

原始碼: Lib/selectors.py


簡介

此模組允許高階和高效的 I/O 多路複用,它構建於 select 模組的原語之上。除非使用者想要精確控制所使用的作業系統級原語,否則建議使用此模組代替。

它定義了一個 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 事件。它可以是模組常量的組合,如下所示

常量

含義

selectors.EVENT_READ

可用於讀取

selectors.EVENT_WRITE

可用於寫入

class selectors.SelectorKey

SelectorKey 是一個 namedtuple,用於將檔案物件與其底層檔案描述符、選定的事件掩碼和附加的資料相關聯。它由幾個 BaseSelector 方法返回。

fileobj

已註冊的檔案物件。

fd

底層檔案描述符。

events

必須在此檔案物件上等待的事件。

data

與此檔案物件關聯的可選不透明資料:例如,這可以用來儲存每個客戶端的會話 ID。

class selectors.BaseSelector

BaseSelector 用於等待多個檔案物件上的 I/O 事件就緒。它支援檔案流的註冊、登出和一個在這些流上等待 I/O 事件的方法,並帶有可選的超時。它是一個抽象基類,因此不能例項化。請改用 DefaultSelector,或者如果希望專門使用某個實現,並且你的平臺支援,請使用 SelectSelectorKqueueSelector 等。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,則呼叫不會阻塞,並將報告當前準備就緒的檔案物件。如果 timeoutNone,則呼叫將阻塞,直到受監視的檔案物件準備就緒。

這將返回一個 (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() 物件使用的檔案描述符。

示例

這是一個簡單的回聲伺服器實現

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)