web-dev-qa-db-fra.com

Différences entre les futurs en Python3 et les promesses dans ES6

Depuis Python 3.5, les mots clés await et async sont introduits dans le langage. Maintenant, je suis plutôt une personne Python 2.7 et j'évite Python 3 depuis un certain temps, donc asyncio est assez nouveau pour moi. D'après ma compréhension, il semble que await/async Fonctionne de manière très similaire à la façon dont ils fonctionnent dans ES6 (ou JavaScript, ES2015, mais vous voulez l'appeler.)

Voici deux scripts que j'ai faits pour les comparer.

import asyncio

async def countdown(n):
    while n > 0:
        print(n)
        n -= 1
        await asyncio.sleep(1)

async def main():
    """Main, executed in an event loop"""

    # Creates two countdowns
    futures = asyncio.gather(
        countdown(3), 
        countdown(2)
    )
    # Wait for all of them to finish
    await futures
    # Exit the app
    loop.stop()

loop = asyncio.get_event_loop()
asyncio.ensure_future(main())
loop.run_forever()
function sleep(n){
    // ES6 does not provide native sleep method with promise support
    return new Promise(res => setTimeout(res, n * 1000));
}

async function countdown(n){
    while(n > 0){
        console.log(n);
        n -= 1;
        await sleep(1);
    }
}

async function main(){
    // Creates two promises
    var promises = Promise.all([
        countdown(3),
        countdown(2)
    ]);
    // Wait for all of them to finish
    await promises;
    // Cannot stop interpreter's event loop
}

main();

Une chose à noter est que les codes sont très similaires et fonctionnent à peu près de la même manière.

Voici les questions:

  1. Dans Python et ES6, await/async Sont basés sur des générateurs. Est-il correct de penser que les Futures sont les mêmes que les Promesses?

  2. J'ai vu les termes Task, Future et Coroutine utilisés dans la documentation asyncio. Quelles sont les différences entre eux?

  3. Dois-je commencer à écrire du code Python qui a toujours une boucle d'événements en cours d'exécution?

19
Derek 朕會功夫
  1. Dans les deux Python et ES6, await/async Sont basés sur des générateurs. Est-il correct de penser que les Futures sont les mêmes que les Promesses?

Pas Future, mais Task de Python est à peu près équivalent à Promise de Javascript. Voir plus de détails ci-dessous.

  1. J'ai vu les termes Task, Future et Coroutine utilisés dans la documentation asyncio. Quelles sont les différences entre eux?

Ce sont des concepts très différents. Principalement, Task se compose de Future et Coroutine. Décrivons brièvement ces primitives (je vais simplifier beaucoup de choses pour ne décrire que les grands principes):

Futur

L'avenir est simplement une abstraction de valeur qui peut ne pas encore être calculée et sera disponible à terme. C'est un simple conteneur qui ne fait qu'une seule chose - chaque fois que la valeur est définie, déclenchez tous les rappels enregistrés.

Si vous souhaitez obtenir cette valeur, vous enregistrez un rappel via la méthode add_done_callback().

Mais contrairement à Promise, le calcul réel est effectué en externe - et ce code externe doit appeler la méthode set_result() pour résoudre l'avenir.

Coroutine

Coroutine est l'objet très similaire à Generator.

Un générateur est généralement itéré dans la boucle for. Il donne valeurs et, à partir de PEP342 acceptation, il reçoit valeurs.

Une coroutine est généralement itérée dans la boucle d'événements dans les profondeurs de la bibliothèque asyncio. Une coroutine renvoie Future instances. Lorsque vous parcourez une coroutine et qu'elle donne un avenir, vous devez attendre que cet avenir soit résolu. Après cela, vous devez send la valeur du futur dans la coroutine, puis vous recevez un autre futur, et ainsi de suite.

Une expression await est pratiquement identique à l'expression yield from, Donc par en attente autre coroutine, vous vous arrêtez jusqu'à ce que cette coroutine ait tout son avenir résolu, et obtenez le retour de la coroutine valeur. Le Future est itérable en une seule fois et son itérateur renvoie le futur réel - cela signifie grosso modo que await future Est égal à yield from future Est égal à yield future.

Tâche

La tâche est Future, qui a en fait commencé à calculer et est attachée à la boucle d'événements. C'est donc un type spécial de Future (la classe Task est dérivée de la classe Future), qui est associée à une boucle d'événement, et elle a une certaine coroutine, qui sert de Exécuteur de tâche.

La tâche est généralement créée par un objet de boucle d'événement: vous donnez une coroutine à la boucle, elle crée un objet de tâche et commence à itérer sur cette coroutine de la manière décrite ci-dessus. Une fois la coroutine terminée, l'avenir de la tâche est résolu par la valeur de retour de la coroutine.

Vous voyez, la tâche est assez similaire à JS Promise - elle encapsule le travail d'arrière-plan et son résultat.

Fonction Coroutine et fonction Async

Coroutine func est une usine de coroutines, comme la fonction de générateur pour les générateurs. Remarquez la différence entre la fonction coroutine de Python et la fonction asynchrone de Javascript - la fonction asynchrone JS, lorsqu'elle est appelée, crée une promesse et son générateur interne commence immédiatement à être itéré, tandis que la coroutine de Python ne fait rien, jusqu'à ce que la tâche soit créée dessus.

  1. Dois-je commencer à écrire Python code qui a toujours une boucle d'événement en cours d'exécution?

Si vous avez besoin d'une fonction asyncio, vous devriez. Il s'avère qu'il est assez difficile de mélanger du code synchrone et asynchrone - dans l'ensemble, votre programme devrait être asynchrone (mais vous pouvez lancer des blocs de code synchrone dans des threads séparés via l'API asyncio threadpool)

25
Andriy Maletsky

Ptyhon et ES6 attendent/async sont à peu près les mêmes, à quelques détails près.

  1. ES6, attendent/async sont basés sur Promise Python: attendent/async sont basés sur Futures. Les générateurs n'ont rien à voir avec cela.
  2. En savoir plus, vous comprendrez ... Coroutine, c'est pour la programmation parallèle, et il existe des moyens de décrire le résultat d'une Coroutine comme un avenir
  3. Utilisez une boucle d'événement lorsque cela a du sens (serveur ou interface graphique événementiel)
0
Walle Cyril