8.11. Aszinkron iterátorok

Az aszinkron iterátor az iterátor asyncio-változata. A Python áttekintés bemutatta a szinkron iterátor-protokollt – __iter__ és __next__ – valamint az azt működtető for ciklust. Az aszinkron iterátorok minden lépéshez hozzáadnak egy await-et, így az iterátor az értékek között várhat anélkül, hogy blokkolná az eseményhurkot.

8.11.1. A protokoll

Egy osztály akkor aszinkron iterátor, ha megvalósítja a következőket:

  • __aiter__(self) – visszaadja az iterátorobjektumot, általában a self-et.

  • async def __anext__(self) – visszaadja a következő értéket, vagy StopAsyncIteration kivételt vált ki, ha nincs több.

A hozzá tartozó ciklusszerkezet az 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)

Az async for ciklus minden __anext__ hívást megvár, így a ciklust futtató korutin az értékek között átadja a vezérlést az eseményhuroknak, akárcsak bármely más await esetén.

8.11.2. Mikor érdemes használni

Mindig, amikor az alkalmazásnak olyan adatforrása van, amely idővel érkezik, és a fogyasztónak lustán kell végigiterálnia rajta. Egy érzékelő, amely periódusonként egy mintát állít elő, egy hálózati socket, amely üzeneteket továbbít, egy képkockagenerátor – bárhol, ahol a while True: x = await source.next(); process(x) forma illeszkedik, az async for x in source a tisztább megfogalmazás.

Olyan forrásoknál, amelyek egy véges befejezési feltételig bocsátanak ki adatokat, az iterátor StopAsyncIteration kivételt vált ki, és az async for normálisan kilép. Olyan forrásoknál, amelyek soha nem érnek véget – folyamatos érzékelőfolyam, hosszan futó előfizetés –, a ciklus addig fut, amíg az őt befogadó korutint meg nem szakítják, vagy a feladatát le nem bontják.