31 votes

Compréhensions asynchrones Python - comment fonctionnent-elles?

Je vais avoir du mal à comprendre l'utilisation de moteurs asynchrones interprétations introduites dans Python 3.6. Comme un avertissement, je n'ai pas beaucoup d'expérience avec le code asynchrone en général en Python.

L'exemple donné dans le quoi de neuf pour Python 3.6 document est:

result = [i async for i in aiter() if i % 2]

Dans le PEP, cela est élargi à:

result = []
async for i in aiter():
    if i % 2:
        result.append(i)

Je pense que je comprends que l' aiter() fonction est appelée de manière asynchrone, de sorte que chaque itération de l' aiter peut procéder sans précédent nécessairement revenir encore (ou est-ce la compréhension de mal?).

Ce que je ne suis pas sûr à ce sujet est de savoir comment cela se traduit alors par la compréhension de liste ici. Les résultats sont placés dans la liste dans l'ordre où ils sont retournés? Ou sont-il efficaces "espaces réservés" dans la liste finale, de sorte que chaque résultat est placé dans la liste dans l'ordre? Ou suis-je de penser à ce sujet dans le mauvais sens?

En outre, quelqu'un est en mesure de fournir des exemples concrets qui illustrent à la fois un cas d'utilisation et de la mécanique de base de la async dans les interprétations de ce genre?

20voto

Martijn Pieters Points 271458

Vous êtes essentiellement demandant comment un async for boucle fonctionne sur un régulier de la boucle. Que vous pouvez maintenant utiliser une boucle de ce genre dans une compréhension de liste ne fait aucune différence ici, c'est juste une optimisation qui permet d'éviter que plusieurs list.append() des appels, exactement comme un normal compréhension de liste n'.

Un async for boucle puis, tout simplement vous attend à chaque étape de l'itération protocole, où régulier for boucle serait de les bloquer.

Pour illustrer, imaginez un normal for boucle:

for foo in bar:
    ...

Pour cette boucle, Python fait essentiellement:

bar_iter = iter(bar)
while True:
    try:
        foo = next(bar_iter)
    except StopIteration:
        break
    ...

L' next(bar_iter) appel n'est pas asynchrone; il bloque.

Maintenant, remplacez for avec async for, et ce que Python n'modifications:

bar_iter = aiter(bar)  # aiter doesn't exist, but see below
while True:
    try:
        foo = await anext(bar_iter)  # anext doesn't exist, but see below
    except StopIteration:
        break
    ...

Dans l'exemple ci - aiter() et anext() sont fictifs fonctions; ces sont fonctionnellement équivalents exacts de leur iter() et next() frères, mais au lieu de __iter__ et __next__ ce __aiter__ et __anext__. C'est-à-dire, asynchrone crochets existent pour la même fonctionnalité, mais sont distingués de leurs non-async variantes par le préfixe a.

L' await mot-clé il y a une différence cruciale, de sorte que pour chaque itération un async for boucle rendements de contrôle afin que les autres coroutines pouvez exécuter à la place.

Encore une fois, à réitérer, déjà tout cela a été ajoutée en Python 3.5 (voir PEP 492), tout ce qui est nouveau en Python 3.6 est que vous pouvez utiliser une boucle de ce genre dans une compréhension de liste aussi. Et dans le générateur d'expressions et de définir et dict interprétations, d'ailleurs.

Dernier mais non le moindre, le même ensemble de changements aussi possible d'utiliser await <expression> dans l'expression de la section d'une compréhension, donc:

[await func(i) for i in someiterable]

est maintenant possible.

11voto

user2357112 Points 37737

Je pense que je comprends que l' aiter() fonction est appelée de manière asynchrone, de sorte que chaque itération de l' aiter peut procéder sans précédent nécessairement revenir encore (ou est-ce la compréhension de mal?).

Cette compréhension est erronée. Itérations de l' async for boucle ne peut pas être effectuées en parallèle. async for est tout aussi séquentielle comme un régulier for boucle.

La partie asynchrone d' async for , c'est qu'il permet à l'itérateur await sur le nom de la coroutine itération sur elle. C'est uniquement pour une utilisation à l'intérieur asynchrone coroutines, et uniquement pour une utilisation sur spécial asynchrone iterables. Autre que cela, c'est surtout une for boucle.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X