8.11. Itérateurs asynchrones¶
Un itérateur asynchrone est la version asyncio d’un itérateur. La présentation de Python a introduit le protocole d’itérateur synchrone – __iter__ et __next__ – ainsi que la boucle for qui le pilote. Les itérateurs asynchrones ajoutent un await à chaque étape, ce qui permet à l’itérateur d”attendre entre deux valeurs sans bloquer la boucle d’événements.
8.11.1. Le protocole¶
Une classe est un itérateur asynchrone lorsqu’elle implémente
__aiter__(self)– renvoie l’objet itérateur, généralementself.async def __anext__(self)– renvoie la valeur suivante, ou lèveStopAsyncIterationlorsqu’il n’y en a plus.
La construction de boucle correspondante est 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)
La boucle async for attend (await) chaque appel à __anext__, de sorte que la coroutine qui exécute la boucle cède la main à la boucle d’événements entre deux valeurs, exactement comme n’importe quel autre await.
8.11.2. Quand y recourir¶
Chaque fois que l’application dispose d’une source de données qui arrive au fil du temps et que le consommateur doit l’itérer paresseusement. Un capteur qui produit un échantillon par période, une socket réseau qui délivre des messages, un générateur de trames – partout où la forme while True: x = await source.next(); process(x) convient, async for x in source en est l’écriture plus propre.
Pour les sources qui émettent jusqu’à une condition de fin finie, l’itérateur lève StopAsyncIteration et async for se termine normalement. Pour les sources qui ne se terminent jamais – un flux de capteur continu, un abonnement de longue durée – la boucle s’exécute jusqu’à ce que la coroutine dans laquelle elle vit soit annulée ou que sa tâche soit démantelée.