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.