8.11. Iteradores asíncronos

Un iterador asíncrono es la versión asyncio de un iterador. La Introducción a Python presentó el protocolo de iteradores síncrono – __iter__ y __next__ – y el bucle for que lo impulsa. Los iteradores asíncronos añaden un await a cada paso, de modo que el iterador puede esperar entre valores sin bloquear el bucle de eventos.

8.11.1. El protocolo

Una clase es un iterador asíncrono cuando implementa

  • __aiter__(self) – devuelve el objeto iterador, normalmente self.

  • async def __anext__(self) – devuelve el siguiente valor, o lanza StopAsyncIteration cuando ya no hay más.

La construcción de bucle correspondiente es 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)

El bucle async for espera (await) cada llamada a __anext__, de modo que la corrutina que ejecuta el bucle cede el control al bucle de eventos entre valores, igual que cualquier otro await.

8.11.2. Cuándo recurrir a ellos

Siempre que la aplicación tenga una fuente de datos que llegan a lo largo del tiempo y el consumidor deba iterarla de forma perezosa. Un sensor que produce una muestra por periodo, un socket de red que entrega mensajes, un generador de fotogramas – en cualquier lugar donde encaje la forma while True: x = await source.next(); process(x), async for x in source es la forma más limpia de escribirlo.

Para fuentes que emiten hasta una condición de fin finita, el iterador lanza StopAsyncIteration y async for finaliza con normalidad. Para fuentes que nunca terminan – un flujo continuo de sensor, una suscripción de larga duración – el bucle se ejecuta hasta que la corrutina en la que vive se cancela o su tarea se desmonta.