8.11. Iteradores assíncronos

Um iterador assíncrono é a versão asyncio de um iterador. A Visão geral do Python apresentou o protocolo síncrono de iterador – __iter__ e __next__ – e o laço for que o conduz. Os iteradores assíncronos adicionam um await a cada passo, de modo que o iterador pode esperar entre os valores sem bloquear o event loop.

8.11.1. O protocolo

Uma classe é um iterador assíncrono quando implementa

  • __aiter__(self) – retorna o objeto iterador, geralmente self.

  • async def __anext__(self) – retorna o próximo valor, ou levanta StopAsyncIteration quando não há mais valores.

A construção de laço correspondente é async for

import asyncio


class FrameCounter:
    """Yield N integers, one per frame period."""

    def __init__(self, n, period_ms):
        self._n = n
        self._period_ms = period_ms
        self._i = 0

    def __aiter__(self):
        return self

    async def __anext__(self):
        if self._i >= self._n:
            raise StopAsyncIteration
        await asyncio.sleep_ms(self._period_ms)
        self._i += 1
        return self._i

async def main():
    async for n in FrameCounter(5, 200):
        print(n)

O laço async for aguarda cada chamada a __anext__, de modo que a corrotina que executa o laço cede o controle ao event loop entre os valores, exatamente como qualquer outro await.

8.11.2. Quando recorrer a ele

Sempre que a aplicação tem uma fonte de dados que chega ao longo do tempo e o consumidor deve iterá-la de forma preguiçosa. Um sensor que produz uma amostra por período, um socket de rede que entrega mensagens, um gerador de quadros – em qualquer lugar onde o formato while True: x = await source.next(); process(x) se encaixa, async for x in source é a forma mais limpa de escrever.

Para fontes que emitem até uma condição final finita, o iterador levanta StopAsyncIteration e o async for termina normalmente. Para fontes que nunca terminam – um fluxo contínuo de sensor, uma assinatura de longa duração – o laço executa até que a corrotina na qual ele vive seja cancelada ou sua tarefa seja desmontada.