select — oczekiwanie na zdarzenia w zbiorze strumieni

Moduł ten udostępnia funkcje pozwalające efektywnie czekać, aż jeden lub więcej strumieni (obiektów plikopodobnych implementujących protokół strumienia, takich jak gniazda, UART-y i inne obiekty I/O) będzie gotowy do odczytu lub zapisu, zamiast aktywnego oczekiwania lub blokowania na pojedynczym obiekcie.

Obiekt poll jest zalecanym interfejsem: skaluje się do wielu strumieni i nie wymaga alokacji, gdy jest używany za pośrednictwem poll.ipoll(). Funkcja select() na poziomie modułu jest mniej wydajnym interfejsem zgodności.

Przykład z użyciem obiektu 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())

Przykład z użyciem funkcji select() na poziomie modułu:

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)

Funkcje

select.select(rlist: List, wlist: List, xlist: List, timeout: float | None = None) Tuple[List, List, List]

Czeka, aż jeden lub więcej z podanych obiektów strumienia będzie gotowy, lub do upłynięcia timeout.

  • rlist to lista obiektów monitorowanych pod kątem gotowości do odczytu.

  • wlist to lista obiektów monitorowanych pod kątem gotowości do zapisu.

  • xlist to lista obiektów monitorowanych pod kątem wystąpienia błędu lub rozłączenia.

  • timeout to maksymalny czas oczekiwania w sekundach (akceptowana jest liczba zmiennoprzecinkowa). Jeśli zostanie pominięty lub wynosi None, wywołanie blokuje w nieskończoność; 0 powoduje natychmiastowy powrót (odpytywanie nieblokujące).

Zwraca 3-elementową krotkę list (rlist, wlist, xlist). Każda zwrócona lista jest podzbiorem odpowiadającej jej listy wejściowej i zawiera obiekty, które stały się gotowe odpowiednio do odczytu, do zapisu lub które zasygnalizowały błąd/rozłączenie. Jeśli timeout upłynie, a nic nie jest gotowe, wszystkie trzy listy są puste.

Funkcja ta jest mniej wydajna niż poll (przy każdym wywołaniu odbudowuje swój wewnętrzny zbiór odpytywania); tam, gdzie to możliwe, używaj zamiast niej poll.

Stałe

select.POLLIN: int

Dostępne są dane do odczytu ze strumienia.

select.POLLOUT: int

Strumień może przyjąć więcej danych do zapisu.

select.POLLERR: int

W strumieniu wystąpił stan błędu. Jest to zdarzenie niezamawiane: jest zgłaszane przez poll.poll() / poll.ipoll(), nawet jeśli nie zostało zażądane w eventmask, i nie można go przekazać jako wejściowy eventmask.

select.POLLHUP: int

Strumień został rozłączony. Jest to zdarzenie niezamawiane: jest zgłaszane przez poll.poll() / poll.ipoll(), nawet jeśli nie zostało zażądane w eventmask, i nie można go przekazać jako wejściowy eventmask.

Klasy

class select.poll

Tworzy obiekt odpytujący, który utrzymuje zbiór zarejestrowanych strumieni (lub dowolnych obiektów udostępniających protokół strumienia) i efektywnie czeka, aż jeden lub więcej z nich stanie się gotowy do odczytu, gotowy do zapisu lub zasygnalizuje stan wyjątkowy.

Strumienie dodaje się za pomocą register(), usuwa za pomocą unregister(), a zbiór obserwowanych zdarzeń można zmienić za pomocą modify(). Po skonfigurowaniu wywołaj poll(), aby zablokować do momentu, gdy coś będzie gotowe (lub upłynie limit czasu), lub ipoll(), aby uzyskać wariant oparty na iteratorze, niewymagający alokacji.

register(obj: Any, eventmask: int = select.POLLIN | select.POLLOUT) None

Rejestruje strumień obj do odpytywania, obserwując zdarzenia podane w eventmask (logiczna suma OR):

eventmask domyślnie wynosi select.POLLIN | select.POLLOUT.

select.POLLHUP i select.POLLERR nie są prawidłowe w wejściowym eventmask – są to zdarzenia niezamawiane, które są zgłaszane przez poll() / ipoll() niezależnie od tego, czy o nie poproszono (jest to zgodne z semantyką POSIX).

Wielokrotne wywołanie tej metody dla tego samego obj jest dozwolone: kolejne wywołanie aktualizuje maskę zdarzeń obj, działając jak modify().

unregister(obj: Any) None

Usuwa obj ze zbioru zarejestrowanych strumieni. Wyrejestrowanie obj, który nie jest aktualnie zarejestrowany, nie jest błędem (w takim przypadku wywołanie nie ma efektu).

modify(obj: Any, eventmask: int) None

Zmienia maskę zdarzeń dla już zarejestrowanego obj na eventmask. Zgłasza OSError z errno.ENOENT, jeśli obj nie jest zarejestrowany.

poll(timeout: int = -1, /) List[Tuple]

Blokuje, dopóki co najmniej jeden zarejestrowany strumień nie stanie się gotowy lub nie zasygnalizuje stanu wyjątkowego, a następnie zwraca listę strumieni, które się uaktywniły.

timeout to maksymalny czas oczekiwania w milisekundach. Jeśli zostanie pominięty lub wynosi -1, wywołanie blokuje w nieskończoność; 0 powoduje natychmiastowy powrót (odpytywanie nieblokujące).

Zwraca listę krotek (obj, event, ...), po jednej na każdy strumień, który się uaktywnił. obj to zarejestrowany strumień, a event to bitowa suma OR flag select.POLLIN / select.POLLOUT / select.POLLERR / select.POLLHUP, które wystąpiły. Każda krotka może zawierać dodatkowe elementy zdefiniowane przez implementację, dlatego nie należy zakładać, że ma dokładnie 2 elementy. Jeśli timeout upłynie, a nic nie jest gotowe, zwracana jest pusta lista.

select.POLLHUP i select.POLLERR mogą zostać zwrócone w dowolnym momencie (nawet jeśli o nie nie poproszono) i należy na nie zareagować – zwykle przez wyrejestrowanie i zamknięcie dotkniętego strumienia – w przeciwnym razie kolejne wywołania będą natychmiast zwracać te flagi ustawione dla tego strumienia.

Wszystkie oczekujące zaplanowane wywołania zwrotne mają gwarancję wykonania przed wejściem do pętli odpytywania.

Różnica względem CPython

Zwracane krotki mogą zawierać więcej niż 2 elementy, jak opisano powyżej.

ipoll(timeout: int = -1, flags: int = 0, /) Iterator[Tuple]

Działa jak poll(), ale zamiast budować listę zwraca iterator, który zwraca po jednej krotce (obj, event, ...) naraz. Pozwala to uniknąć alokacji przy każdym wywołaniu, co jest ważne dla asynchronicznych schedulerów I/O.

Zwracana krotka jest własnością wywoływanego: jest ponownie używana (nadpisywana) przy następnej iteracji, więc jej zawartość należy skonsumować w obrębie ciała pętli, a referencji do niej nie wolno przechowywać.

timeout ma takie samo znaczenie jak w poll(). Jeśli flags wynosi 1, używane jest zachowanie jednorazowe: strumień, którego zdarzenie się uaktywniło, ma automatycznie czyszczoną maskę zdarzeń (odpowiednik poll.modify(obj, 0)), więc nie są dla niego zgłaszane żadne kolejne zdarzenia, dopóki jego maska nie zostanie ponownie ustawiona za pomocą modify().

Wszystkie oczekujące zaplanowane wywołania zwrotne mają gwarancję wykonania przed wejściem do pętli odpytywania.

Różnica względem CPython

Ta metoda jest rozszerzeniem MicroPython.