8.11. Iteratori asincroni

Un iterator asincron este versiunea asyncio a unui iterator. Prezentarea generală Python a introdus protocolul iteratorului sincron – __iter__ și __next__ – și bucla for care îl pune în mișcare. Iteratorii asincroni adaugă un await la fiecare pas, astfel încât iteratorul poate aștepta între valori fără a bloca bucla de evenimente.

8.11.1. Protocolul

O clasă este un iterator asincron atunci când implementează

  • __aiter__(self) – returnează obiectul iterator, de obicei self.

  • async def __anext__(self) – returnează valoarea următoare sau ridică StopAsyncIteration atunci când nu mai există valori.

Construcția de buclă corespunzătoare este 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)

Bucla async for așteaptă fiecare apel către __anext__, astfel încât corutina care execută bucla cedează controlul buclei de evenimente între valori, exact ca orice alt await.

8.11.2. Când să apelezi la el

Ori de câte ori aplicația are o sursă de date care sosesc în timp și consumatorul ar trebui să le itereze în mod leneș. Un senzor care produce o eșantionare pe perioadă, un socket de rețea care livrează mesaje, un generator de cadre – oriunde se potrivește forma while True: x = await source.next(); process(x), async for x in source este formularea mai curată.

Pentru surse care emit până la o condiție de încheiere finită, iteratorul ridică StopAsyncIteration și async for se încheie normal. Pentru surse care nu se termină niciodată – un flux continuu de la un senzor, un abonament de lungă durată – bucla rulează până când corutina în care se află este anulată sau sarcina sa este desființată.