8.11. Asinkroni iteratori

Asinkroni iterator je asyncio inačica iteratora. Pregled Pythona predstavio je sinkroni protokol iteratora – __iter__ i __next__ – te petlju for koja ga pogoni. Asinkroni iteratori dodaju await svakom koraku, tako da iterator može čekati između vrijednosti bez blokiranja petlje događaja.

8.11.1. Protokol

Klasa je asinkroni iterator kada implementira

  • __aiter__(self) – vraća objekt iteratora, obično self.

  • async def __anext__(self) – vraća sljedeću vrijednost ili podiže StopAsyncIteration kada ih više nema.

Odgovarajuća konstrukcija petlje je 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)

Petlja async for čeka svaki poziv na __anext__, tako da korutina koja izvodi petlju prepušta kontrolu petlji događaja između vrijednosti, baš kao i svaki drugi await.

8.11.2. Kada ga upotrijebiti

Kad god aplikacija ima izvor podataka koji pristižu tijekom vremena, a potrošač bi ih trebao iterirati lijeno. Senzor koji proizvodi uzorak po razdoblju, mrežna utičnica koja isporučuje poruke, generator sličica – gdje god odgovara oblik while True: x = await source.next(); process(x), async for x in source je čišći način zapisa.

Za izvore koji emitiraju do konačnog uvjeta završetka, iterator podiže StopAsyncIteration i async for normalno izlazi. Za izvore koji nikada ne završavaju – kontinuirani tok senzora, dugotrajna pretplata – petlja se izvodi sve dok se korutina u kojoj živi ne otkaže ili dok se njezin zadatak ne ukine.