select — attende eventi su un insieme di stream

Questo modulo fornisce funzioni per attendere in modo efficiente finché uno o più stream (oggetti simili a file che implementano il protocollo di stream, come socket, UART e altri oggetti di I/O) sono pronti per la lettura o la scrittura, invece di eseguire un’attesa attiva o di bloccarsi su un singolo oggetto.

L’oggetto poll è l’interfaccia consigliata: scala bene con molti stream ed è privo di allocazioni quando usato tramite poll.ipoll(). La funzione select() a livello di modulo è un’interfaccia di compatibilità meno efficiente.

Esempio che usa un oggetto 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())

Esempio che usa la funzione select() a livello di modulo:

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)

Funzioni

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

Attende finché uno o più degli oggetti stream forniti è pronto, oppure finché scade timeout.

  • rlist è una lista di oggetti da monitorare per la leggibilità.

  • wlist è una lista di oggetti da monitorare per la scrivibilità.

  • xlist è una lista di oggetti da monitorare per una condizione di errore o di disconnessione.

  • timeout è il tempo massimo di attesa, in secondi (è accettato un float). Se viene omesso o è None la chiamata si blocca indefinitamente; 0 ritorna immediatamente (un polling non bloccante).

Restituisce una tupla di 3 liste (rlist, wlist, xlist). Ogni lista restituita è il sottoinsieme della lista di input corrispondente contenente gli oggetti che sono diventati pronti per la lettura, pronti per la scrittura, o che hanno segnalato un errore/una disconnessione, rispettivamente. Se timeout scade senza che nulla sia pronto, tutte e tre le liste sono vuote.

Questa funzione è meno efficiente di poll (ricostruisce il proprio insieme di polling interno a ogni chiamata); usa invece poll dove possibile.

Costanti

select.POLLIN: int

Ci sono dati disponibili da leggere dallo stream.

select.POLLOUT: int

Lo stream può accettare altri dati da scrivere.

select.POLLERR: int

Si è verificata una condizione di errore sullo stream. Questo è un evento non sollecitato: viene segnalato da poll.poll() / poll.ipoll() anche se non è stato richiesto nell”eventmask, e non è valido passarlo come eventmask di input.

select.POLLHUP: int

Lo stream è stato disconnesso / chiuso. Questo è un evento non sollecitato: viene segnalato da poll.poll() / poll.ipoll() anche se non è stato richiesto nell”eventmask, e non è valido passarlo come eventmask di input.

Classi

class select.poll

Crea un oggetto di polling che mantiene un insieme di stream registrati (o qualsiasi oggetto che espone il protocollo di stream) e attende in modo efficiente finché uno o più di essi diventa leggibile, scrivibile, o segnala una condizione eccezionale.

Gli stream vengono aggiunti con register(), rimossi con unregister(), e l’insieme degli eventi da osservare può essere modificato con modify(). Una volta configurato, chiama poll() per bloccare finché qualcosa è pronto (o finché scade un timeout), oppure ipoll() per una variante basata su iteratore e priva di allocazioni.

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

Registra lo stream obj per il polling, osservando gli eventi indicati da eventmask (l’OR logico di):

eventmask ha come valore predefinito select.POLLIN | select.POLLOUT.

select.POLLHUP e select.POLLERR non sono validi in un eventmask di input – sono eventi non sollecitati che vengono segnalati da poll() / ipoll() indipendentemente dal fatto che siano stati richiesti (questo corrisponde alla semantica POSIX).

È lecito chiamare questo metodo più di una volta per lo stesso obj: una chiamata successiva aggiorna la maschera degli eventi di obj, comportandosi come modify().

unregister(obj: Any) None

Rimuove obj dall’insieme degli stream registrati. Non è un errore deregistrare un obj che non è attualmente registrato (in tal caso la chiamata non ha alcun effetto).

modify(obj: Any, eventmask: int) None

Modifica la maschera degli eventi di un obj già registrato in eventmask. Solleva OSError con errno.ENOENT se obj non è registrato.

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

Blocca finché almeno uno stream registrato diventa pronto o segnala una condizione eccezionale, poi restituisce la lista degli stream che si sono attivati.

timeout è il tempo massimo di attesa in millisecondi. Se viene omesso o è -1 la chiamata si blocca indefinitamente; 0 ritorna immediatamente (un polling non bloccante).

Restituisce una lista di tuple (obj, event, ...), una per ogni stream che si è attivato. obj è lo stream registrato ed event è l’OR bit a bit dei flag select.POLLIN / select.POLLOUT / select.POLLERR / select.POLLHUP che si sono verificati. Ogni tupla può contenere ulteriori elementi definiti dall’implementazione, quindi non dare per scontata una lunghezza esattamente pari a 2. Se timeout scade senza che nulla sia pronto, viene restituita una lista vuota.

select.POLLHUP e select.POLLERR possono essere restituiti in qualsiasi momento (anche se non richiesti) e si deve agire di conseguenza – tipicamente deregistrando e chiudendo lo stream interessato – altrimenti le chiamate successive continueranno a ritornare immediatamente con questi flag impostati per quello stream.

È garantito che eventuali callback pianificate in sospeso vengano eseguite prima di entrare nel ciclo di polling.

Differenza rispetto a CPython

Le tuple restituite possono contenere più di 2 elementi, come descritto sopra.

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

Come poll(), ma invece di costruire una lista restituisce un iteratore che produce una tupla (obj, event, ...) alla volta. Questo evita di allocare a ogni chiamata, il che è importante per gli scheduler di I/O asincrono.

La tupla prodotta è di proprietà del chiamato: viene riutilizzata (sovrascritta) all’iterazione successiva, quindi il suo contenuto deve essere consumato all’interno del corpo del ciclo e non si devono memorizzare riferimenti ad essa.

timeout ha lo stesso significato che ha per poll(). Se flags è 1, viene usato il comportamento one-shot: a uno stream il cui evento si è attivato viene azzerata automaticamente la maschera degli eventi (equivalente a poll.modify(obj, 0)), così non vengono più segnalati ulteriori eventi per esso finché la sua maschera non viene reimpostata con modify().

È garantito che eventuali callback pianificate in sospeso vengano eseguite prima di entrare nel ciclo di polling.

Differenza rispetto a CPython

Questo metodo è un’estensione di MicroPython.