Aller au contenu

Parcourir des données de manière asynchrone

aiter() : obtenir un itérateur asynchrone

Disponible depuis Python 3.10, aiter() obtient l'itérateur d'un itérable asynchrone. Contrairement à iter(), elle ne possède pas de forme à deux arguments.

async def generate_numbers():
    yield 10
    yield 20

iterator = aiter(generate_numbers())
# Le parcours et l'attente des valeurs sont montrés avec anext() ci-dessous.

Equivalent en C#

static async IAsyncEnumerable<int> GenerateNumbers()
{
    await Task.Yield();
    yield return 10;
    yield return 20;
}

await using IAsyncEnumerator<int> iterator = GenerateNumbers().GetAsyncEnumerator();
while (await iterator.MoveNextAsync())
    Console.WriteLine(iterator.Current);

GetAsyncEnumerator() correspond à l’obtention d’un itérateur asynchrone. await using libère ses ressources. Un await foreach est généralement préférable pour un parcours courant. Le bloc C# est indépendant du suivant.

anext() : attendre l'élément asynchrone suivant

Également disponible depuis Python 3.10, anext() renvoie un objet à attendre avec await. Lorsque le parcours est terminé, elle lève StopAsyncIteration, sauf si une valeur de remplacement est précisée.

L'exemple suivant illustre les deux fonctions. Le module standard asyncio est importé uniquement pour exécuter la coroutine depuis un script.

import asyncio

async def generate_numbers():
    yield 10
    yield 20

async def main():
    iterator = aiter(generate_numbers())
    print(await anext(iterator))        # 10
    print(await anext(iterator))        # 20
    print(await anext(iterator, None))  # None

asyncio.run(main())

Dans un environnement disposant déjà d'une boucle asynchrone, l'exécution de main() doit s'intégrer à cette boucle. Pour un parcours courant, async for est généralement plus simple.

Equivalent en C#

static async IAsyncEnumerable<int> GenerateNumbers()
{
    await Task.Yield();
    yield return 10;
}

await using var iterator = GenerateNumbers().GetAsyncEnumerator();
if (await iterator.MoveNextAsync())
    Console.WriteLine(iterator.Current); // 10
int? value = await iterator.MoveNextAsync() ? iterator.Current : null;
Console.WriteLine(value is null); // True

MoveNextAsync() signale l’existence d’une valeur avec un booléen ; Current fournit ensuite la valeur. anext() attend directement la valeur et signale la fin par une exception ou une valeur de remplacement.