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 aself-et.async def __anext__(self)– visszaadja a következő értéket, vagyStopAsyncIterationkivé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.