8.11. Asynkroniset iteraattorit

Asynkroninen iteraattori on iteraattorin asyncio-versio. Python-yleiskatsaus esitteli synkronisen iteraattoriprotokollan – __iter__ ja __next__ – sekä sitä ohjaavan for-silmukan. Asynkroniset iteraattorit lisäävät jokaiseen vaiheeseen await-lauseen, joten iteraattori voi odottaa arvojen välillä estämättä tapahtumasilmukkaa.

8.11.1. Protokolla

Luokka on asynkroninen iteraattori, kun se toteuttaa

  • __aiter__(self) – palauttaa iteraattoriobjektin, yleensä self.

  • async def __anext__(self) – palauttaa seuraavan arvon tai nostaa StopAsyncIteration, kun arvoja ei ole enää jäljellä.

Vastaava silmukkarakenne on 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 -silmukka odottaa jokaista __anext__ -kutsua, joten silmukkaa suorittava korutiini luovuttaa vuoron tapahtumasilmukalle arvojen välillä aivan kuten mikä tahansa muu await.

8.11.2. Milloin sitä kannattaa käyttää

Aina kun sovelluksella on tietolähde, joka saapuu ajan myötä ja jota kuluttajan tulisi iteroida laiskasti. Sensori, joka tuottaa näytteen jaksoa kohden, verkkosoketti, joka toimittaa viestejä, kehysgeneraattori – kaikkialla, missä muoto while True: x = await source.next(); process(x) sopii, async for x in source on siistimpi ilmaisutapa.

Lähteille, jotka tuottavat dataa äärelliseen loppuehtoon asti, iteraattori nostaa StopAsyncIteration ja async for poistuu normaalisti. Lähteille, jotka eivät koskaan pääty – jatkuva sensorivirta, pitkäkestoinen tilaus – silmukka jatkuu, kunnes korutiini, jossa se elää, perutaan tai sen tehtävä puretaan.