select — aguardar eventos num conjunto de streams

Este módulo fornece funções para aguardar eficientemente até que um ou mais streams (objetos semelhantes a ficheiros que implementam o protocolo de stream, como sockets, UARTs e outros objetos de I/O) estejam prontos para leitura ou escrita, em vez de realizar busy-waiting ou bloquear num único objeto.

O objeto poll é a interface recomendada: escala para muitos streams e não faz alocações quando utilizado através de poll.ipoll(). A função select() ao nível do módulo é uma interface de compatibilidade menos eficiente.

Exemplo utilizando um objeto 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())

Exemplo utilizando a função select() ao nível do módulo:

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)

Funções

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

Aguarda até que um ou mais dos objetos de stream fornecidos estejam prontos, ou até que timeout expire.

  • rlist é uma lista de objetos a monitorizar para leitura.

  • wlist é uma lista de objetos a monitorizar para escrita.

  • xlist é uma lista de objetos a monitorizar para uma condição de erro ou hang-up.

  • timeout é o tempo máximo de espera, em segundos (é aceite um float). Se for omitido ou None, a chamada bloqueia indefinidamente; 0 retorna imediatamente (sondagem não bloqueante).

Devolve um tuplo de 3 listas (rlist, wlist, xlist). Cada lista devolvida é o subconjunto da lista de entrada correspondente que contém os objetos que ficaram prontos para leitura, prontos para escrita, ou que sinalizaram um erro/hang-up, respetivamente. Se timeout expirar sem nada pronto, as três listas estão vazias.

Esta função é menos eficiente do que poll (reconstrói o seu conjunto de sondagem interno em cada chamada); utilize poll em alternativa sempre que possível.

Constantes

select.POLLIN: int

Existem dados disponíveis para ler a partir do stream.

select.POLLOUT: int

O stream pode aceitar mais dados para escrita.

select.POLLERR: int

Ocorreu uma condição de erro no stream. Este é um evento não solicitado: é reportado por poll.poll() / poll.ipoll() mesmo que não tenha sido pedido no eventmask, e não é válido passá-lo como eventmask de entrada.

select.POLLHUP: int

O stream foi desligado/desconectado. Este é um evento não solicitado: é reportado por poll.poll() / poll.ipoll() mesmo que não tenha sido pedido no eventmask, e não é válido passá-lo como eventmask de entrada.

Classes

class select.poll

Cria um objeto de sondagem que mantém um conjunto de streams registados (ou quaisquer objetos que exponham o protocolo de stream) e aguarda eficientemente até que um ou mais deles fique legível, gravável ou sinalize uma condição excecional.

Os streams são adicionados com register(), removidos com unregister(), e o conjunto de eventos a monitorizar pode ser alterado com modify(). Uma vez configurado, chame poll() para bloquear até que algo esteja pronto (ou expire um timeout), ou ipoll() para uma variante baseada em iterador sem alocações.

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

Regista o stream obj para sondagem, monitorizando os eventos dados por eventmask (o OR lógico de):

eventmask tem como valor predefinido select.POLLIN | select.POLLOUT.

select.POLLHUP e select.POLLERR não são válidos num eventmask de entrada – são eventos não solicitados reportados por poll() / ipoll() independentemente de terem sido pedidos (isto corresponde à semântica POSIX).

É permitido chamar este método mais do que uma vez para o mesmo obj: uma chamada subsequente atualiza a máscara de eventos de obj, comportando-se como modify().

unregister(obj: Any) None

Remove obj do conjunto de streams registados. Não é um erro desregistar um obj que não esteja atualmente registado (a chamada não tem efeito nesse caso).

modify(obj: Any, eventmask: int) None

Altera a máscara de eventos de um obj já registado para eventmask. Lança OSError com errno.ENOENT se obj não estiver registado.

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

Bloqueia até que pelo menos um stream registado fique pronto ou sinalize uma condição excecional, e devolve a lista de streams que dispararam.

timeout é o tempo máximo de espera em milissegundos. Se for omitido ou -1, a chamada bloqueia indefinidamente; 0 retorna imediatamente (sondagem não bloqueante).

Devolve uma lista de tuplos (obj, event, ...), um por stream que disparou. obj é o stream registado e event é o OR bit a bit dos sinalizadores select.POLLIN / select.POLLOUT / select.POLLERR / select.POLLHUP que ocorreram. Cada tuplo pode conter elementos adicionais definidos pela implementação, por isso não assuma um comprimento exatamente igual a 2. Se timeout expirar sem nada pronto, é devolvida uma lista vazia.

select.POLLHUP e select.POLLERR podem ser devolvidos a qualquer momento (mesmo que não tenham sido pedidos) e devem ser tratados – tipicamente desregistando e fechando o stream afetado – caso contrário as chamadas subsequentes continuarão a retornar imediatamente com estes sinalizadores definidos para esse stream.

Quaisquer callbacks agendados pendentes têm a garantia de ser executados antes de entrar no ciclo de sondagem.

Diferença em relação ao CPython

Os tuplos devolvidos podem conter mais de 2 elementos, conforme descrito acima.

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

Semelhante a poll(), mas em vez de construir uma lista, devolve um iterador que produz um tuplo (obj, event, ...) de cada vez. Isto evita alocações em cada chamada, o que é importante para os agendadores de I/O assíncrono.

O tuplo produzido pertence ao callee: é reutilizado (sobrescrito) na próxima iteração, pelo que o seu conteúdo deve ser consumido dentro do corpo do ciclo e não devem ser guardadas referências para ele.

timeout tem o mesmo significado que em poll(). Se flags for 1, é utilizado comportamento one-shot: um stream cujo evento disparou tem a sua máscara de eventos automaticamente limpa (equivalente a poll.modify(obj, 0)), pelo que não são reportados mais eventos para ele até que a sua máscara seja definida novamente com modify().

Quaisquer callbacks agendados pendentes têm a garantia de ser executados antes de entrar no ciclo de sondagem.

Diferença em relação ao CPython

Este método é uma extensão MicroPython.