8.11. Asynkrona iteratorer¶
En asynkron iterator är asyncio-versionen av en iterator. Python-översikten introducerade det synkrona iteratorprotokollet – __iter__ och __next__ – samt for-loopen som driver det. Asynkrona iteratorer lägger till ett await i varje steg, så att iteratorn kan vänta mellan värdena utan att blockera händelseloopen.
8.11.1. Protokollet¶
En klass är en asynkron iterator när den implementerar
__aiter__(self)– returnerar iteratorobjektet, vanligtvisself.async def __anext__(self)– returnerar nästa värde, eller höjerStopAsyncIterationnär det inte finns några fler.
Motsvarande loopkonstruktion är 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)
async for-loopen inväntar varje anrop till __anext__, så att den coroutine som kör loopen lämnar över till händelseloopen mellan värdena precis som vilket annat await som helst.
8.11.2. När den ska användas¶
När applikationen har en datakälla som anländer över tid och konsumenten bör iterera den lat. En sensor som producerar ett sampel per period, ett nätverkssocket som levererar meddelanden, en bildrutegenerator – överallt där formen while True: x = await source.next(); process(x) passar är async for x in source det renare uttrycket.
För källor som sänder fram till ett ändligt slutvillkor höjer iteratorn StopAsyncIteration och async for avslutas normalt. För källor som aldrig tar slut – en kontinuerlig sensorström, en långvarig prenumeration – körs loopen tills den coroutine den lever i avbryts eller dess uppgift rivs ned.