select — auf Ereignisse auf einer Menge von Streams warten

Dieses Modul stellt Funktionen bereit, um effizient zu warten, bis einer oder mehrere streams (dateiähnliche Objekte, die das Stream-Protokoll implementieren, wie Sockets, UARTs und andere I/O-Objekte) zum Lesen oder Schreiben bereit ist, anstatt aktiv abzuwarten (Busy-Waiting) oder auf einem einzelnen Objekt zu blockieren.

Das poll-Objekt ist die empfohlene Schnittstelle: Es skaliert auf viele Streams und ist allokationsfrei, wenn es über poll.ipoll() verwendet wird. Die Funktion select() auf Modulebene ist eine weniger effiziente Kompatibilitätsschnittstelle.

Beispiel mit einem poll-Objekt:

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())

Beispiel mit der select()-Funktion auf Modulebene:

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)

Funktionen

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

Wartet, bis eines oder mehrere der angegebenen Stream-Objekte bereit ist, oder bis timeout abläuft.

  • rlist ist eine Liste von Objekten, die auf Lesbarkeit überwacht werden sollen.

  • wlist ist eine Liste von Objekten, die auf Schreibbarkeit überwacht werden sollen.

  • xlist ist eine Liste von Objekten, die auf eine Fehler- oder Verbindungsabbruchbedingung überwacht werden sollen.

  • timeout ist die maximale Wartezeit in Sekunden (ein Float wird akzeptiert). Wenn es weggelassen wird oder None ist, blockiert der Aufruf unbegrenzt; 0 kehrt sofort zurück (ein nicht blockierendes Poll).

Gibt ein 3-Tupel von Listen (rlist, wlist, xlist) zurück. Jede zurückgegebene Liste ist die Teilmenge der entsprechenden Eingabeliste, die jeweils die Objekte enthält, die zum Lesen bereit wurden, zum Schreiben bereit wurden oder einen Fehler bzw. Verbindungsabbruch signalisiert haben. Wenn timeout abläuft, ohne dass etwas bereit ist, sind alle drei Listen leer.

Diese Funktion ist weniger effizient als poll (sie baut bei jedem Aufruf ihre interne Poll-Menge neu auf); verwenden Sie nach Möglichkeit stattdessen poll.

Konstanten

select.POLLIN: int

Es sind Daten zum Lesen aus dem Stream verfügbar.

select.POLLOUT: int

Der Stream kann weitere zu schreibende Daten aufnehmen.

select.POLLERR: int

Eine Fehlerbedingung ist auf dem Stream aufgetreten. Dies ist ein unaufgefordertes Ereignis: Es wird von poll.poll() / poll.ipoll() gemeldet, auch wenn es nicht in der eventmask angefordert wurde, und es ist nicht gültig, es als Eingabe-eventmask zu übergeben.

select.POLLHUP: int

Der Stream wurde aufgelegt / getrennt. Dies ist ein unaufgefordertes Ereignis: Es wird von poll.poll() / poll.ipoll() gemeldet, auch wenn es nicht in der eventmask angefordert wurde, und es ist nicht gültig, es als Eingabe-eventmask zu übergeben.

Klassen

class select.poll

Erstellt ein Polling-Objekt, das eine Menge registrierter Streams (oder beliebiger Objekte, die das Stream-Protokoll bereitstellen) verwaltet und effizient wartet, bis einer oder mehrere von ihnen lesbar oder schreibbar werden oder eine Ausnahmebedingung signalisieren.

Streams werden mit register() hinzugefügt, mit unregister() entfernt, und die Menge der zu überwachenden Ereignisse kann mit modify() geändert werden. Sobald konfiguriert, rufen Sie poll() auf, um zu blockieren, bis etwas bereit ist (oder ein Timeout abläuft), oder ipoll() für eine allokationsfreie, iteratorbasierte Variante.

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

Registriert den stream obj für das Polling und überwacht die durch eventmask angegebenen Ereignisse (die logische ODER-Verknüpfung von):

eventmask ist standardmäßig select.POLLIN | select.POLLOUT.

select.POLLHUP und select.POLLERR sind in einer Eingabe-eventmask nicht gültig – es handelt sich um unaufgeforderte Ereignisse, die von poll() / ipoll() gemeldet werden, unabhängig davon, ob sie angefordert wurden (dies entspricht der POSIX-Semantik).

Es ist in Ordnung, diese Methode mehr als einmal für dasselbe obj aufzurufen: Ein nachfolgender Aufruf aktualisiert die Ereignismaske von obj und verhält sich wie modify().

unregister(obj: Any) None

Entfernt obj aus der Menge der registrierten Streams. Es ist kein Fehler, ein obj zu deregistrieren, das aktuell nicht registriert ist (der Aufruf hat in diesem Fall keine Wirkung).

modify(obj: Any, eventmask: int) None

Ändert die Ereignismaske für ein bereits registriertes obj auf eventmask. Löst OSError mit errno.ENOENT aus, falls obj nicht registriert ist.

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

Blockiert, bis mindestens ein registrierter Stream bereit wird oder eine Ausnahmebedingung signalisiert, und gibt dann die Liste der Streams zurück, die ausgelöst haben.

timeout ist die maximale Wartezeit in Millisekunden. Wenn es weggelassen wird oder -1 ist, blockiert der Aufruf unbegrenzt; 0 kehrt sofort zurück (ein nicht blockierendes Poll).

Gibt eine Liste von (obj, event, ...)-Tupeln zurück, eines pro Stream, der ausgelöst hat. obj ist der registrierte Stream und event ist die bitweise ODER-Verknüpfung der aufgetretenen Flags select.POLLIN / select.POLLOUT / select.POLLERR / select.POLLHUP. Jedes Tupel kann zusätzliche implementierungsdefinierte Elemente enthalten, gehen Sie also nicht von einer Länge von genau 2 aus. Wenn timeout abläuft, ohne dass etwas bereit ist, wird eine leere Liste zurückgegeben.

select.POLLHUP und select.POLLERR können jederzeit zurückgegeben werden (auch wenn nicht angefordert) und müssen behandelt werden – typischerweise durch Deregistrieren und Schließen des betroffenen Streams – andernfalls kehren nachfolgende Aufrufe weiterhin sofort zurück, wobei diese Flags für diesen Stream gesetzt sind.

Es ist garantiert, dass alle ausstehenden geplanten Callbacks ausgeführt werden, bevor die Polling-Schleife betreten wird.

Unterschied zu CPython

Zurückgegebene Tupel können mehr als 2 Elemente enthalten, wie oben beschrieben.

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

Wie poll(), aber anstatt eine Liste aufzubauen, wird ein Iterator zurückgegeben, der jeweils ein (obj, event, ...)-Tupel liefert. Dies vermeidet eine Allokation bei jedem Aufruf, was für asynchrone I/O-Scheduler wichtig ist.

Das gelieferte Tupel ist callee-owned: Es wird bei der nächsten Iteration wiederverwendet (überschrieben), daher muss sein Inhalt innerhalb des Schleifenkörpers verarbeitet werden, und Referenzen darauf dürfen nicht gespeichert werden.

timeout hat dieselbe Bedeutung wie bei poll(). Wenn flags 1 ist, wird One-Shot-Verhalten verwendet: Bei einem Stream, dessen Ereignis ausgelöst hat, wird seine Ereignismaske automatisch gelöscht (entspricht poll.modify(obj, 0)), sodass keine weiteren Ereignisse für ihn gemeldet werden, bis seine Maske mit modify() erneut gesetzt wird.

Es ist garantiert, dass alle ausstehenden geplanten Callbacks ausgeführt werden, bevor die Polling-Schleife betreten wird.

Unterschied zu CPython

Diese Methode ist eine MicroPython-Erweiterung.