8.11. Asynchronní iterátory¶
Asynchronní iterátor je asyncio verzí iterátoru. Přehled jazyka Python představil synchronní protokol iterátoru – __iter__ a __next__ – a smyčku for, která jej řídí. Asynchronní iterátory přidávají do každého kroku await, takže iterátor může mezi hodnotami čekat, aniž by blokoval smyčku událostí.
8.11.1. Protokol¶
Třída je asynchronním iterátorem, pokud implementuje
__aiter__(self)– vrací objekt iterátoru, obvykleself.async def __anext__(self)– vrací další hodnotu, nebo vyvoláStopAsyncIteration, když už žádné nezbývají.
Odpovídající konstrukcí smyčky 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)
Smyčka async for čeká (await) na každé volání __anext__, takže korutina, která smyčku provádí, mezi hodnotami předává řízení smyčce událostí stejně jako u jakéhokoli jiného await.
8.11.2. Kdy po něm sáhnout¶
Vždy, když má aplikace zdroj dat, který přichází v průběhu času, a konzument jej má procházet líně. Senzor, který produkuje jeden vzorek za periodu, síťový soket doručující zprávy, generátor snímků – všude, kam se hodí tvar while True: x = await source.next(); process(x), je async for x in source čistším zápisem.
U zdrojů, které vysílají až do konečné koncové podmínky, iterátor vyvolá StopAsyncIteration a async for skončí běžným způsobem. U zdrojů, které nikdy nekončí – nepřetržitý proud ze senzoru, dlouhodobé odebírání – smyčka běží, dokud není zrušena korutina, ve které žije, nebo dokud není zlikvidována její úloha.