Futures

Code source : Lib/asyncio/futures.py, Lib/asyncio/base_futures.py


Les objets Future sont utilisés comme passerelles entre du code bas niveau basé sur des fonctions de rappel et du code haut niveau utilisant async et await.

Fonctions pour Future

asyncio.isfuture(obj)

Renvoie True si obj est soit :

  • une instance de asyncio.Future ;

  • une instance de asyncio.Task ;

  • un objet se comportant comme Future et possédant un attribut _asyncio_future_blocking.

Nouveau dans la version 3.5.

asyncio.ensure_future(obj, *, loop=None)

Renvoie :

  • l'objet obj tel quel si c'est un objet Future, Task ou se comportant comme un Future. isfuture() est utilisée pour le test ;

  • un objet Task encapsulant obj si ce dernier est une coroutine (iscoroutine() est utilisée pour le test). Dans ce cas, l’exécution de la coroutine sera planifiée par ensure_future() ;

  • un objet Task qui attendra (await) obj si ce dernier peut être attendu (awaitable). iscoroutine() est utilisée pour le test.

Si obj ne correspond à aucun des critères ci-dessus, une exception TypeError est levée.

Important

Voir aussi la fonction create_task() qui est la manière privilégiée pour créer des nouvelles tâches.

Gardez une référence au résultat de cette fonction pour éviter de voir une tâche disparaitre au milieu de son exécution.

Modifié dans la version 3.5.1: La fonction accepte n'importe quel objet awaitable.

Obsolète depuis la version 3.10: Un DeprecationWarning est levé si obj n'est pas un objet se comportant comme un Future, si loop n'est pas spécifié et s'il n'y a pas de boucle d'évènements en cours d'exécution.

asyncio.wrap_future(future, *, loop=None)

Encapsule un objet concurrent.futures.Future dans un objet asyncio.Future.

Obsolète depuis la version 3.10: Un DeprecationWarning est levé si future n'est pas un objet se comportant comme un Future, si loop n'est pas spécifié et s'il n'y a pas de boucle d'évènements en cours d'exécution.

Objet Future

class asyncio.Future(*, loop=None)

Un Future représente le résultat final d'une opération asynchrone. Il n'est pas conçu pour pouvoir être utilisé par plusieurs fils d'exécution.

Future est un objet qui peut être attendu (awaitable). Les coroutines peuvent attendre les objets Future jusqu'à ce qu'ils renvoient un résultat, ils lèvent une exception ou qu'ils soient annulés. Un Future peut être attendu plusieurs fois et le résultat est le même.

Les Futures sont habituellement utilisés pour permettre à du code bas niveau basé sur des fonctions de rappel (par exemple : les protocoles utilisant asyncio transports) d'interagir avec du code haut niveau utilisant async et await.

Une bonne règle empirique est de ne jamais exposer des objets Future dans des API destinées à l'utilisateur. La façon privilégiée de créer des objets Future est d'appeler la méthode loop.create_future(). Cela permet aux implémentations alternatives de la boucle d'évènements d'utiliser leur propre implémentation de l'objet Future.

Modifié dans la version 3.7: Ajout du support du module contextvars.

Obsolète depuis la version 3.10: Un DeprecationWarning est levé si loop n'est pas spécifié et s'il n'y a pas de boucle d'évènements en cours d'exécution.

result()

Renvoie le résultat du Future.

Si le Future est « terminé » et a un résultat défini par la méthode set_result(), ce résultat est renvoyé.

Si le Future est « terminé » et a une exception définie par la méthode set_exception(), cette méthode lève l'exception.

Si le Future a été annulé, cette méthode lève une exception CancelledError.

Si le résultat de la tâche n'est pas encore disponible, cette méthode lève une exception InvalidStateError.

set_result(result)

Marque le Future comme « terminé » et définit son résultat.

Lève une erreur InvalidStateError si le Future est déjà « terminé ».

set_exception(exception)

Marque le Future comme « terminé » et définit une exception.

Lève une erreur InvalidStateError si le Future est déjà « terminé ».

done()

Renvoie True si le Future est « terminé ».

Un Future est « terminé » s'il a été « annulé » ou si un résultat ou une exception a été définie par les méthodes set_result() ou set_exception().

cancelled()

Renvoie True si le Future a été « annulé ».

Cette méthode est habituellement utilisée pour vérifier qu'un Future n'est pas « annulé » avant de définir un résultat ou une exception pour celui-ci :

if not fut.cancelled():
    fut.set_result(42)
add_done_callback(callback, *, context=None)

Ajoute une fonction de rappel à exécuter lorsque le Future est « terminé ».

L'argument callback est appelé avec l'objet Future comme seul argument.

Si le Future est déjà « terminé » lorsque la méthode est appelée, l'exécution de la fonction de rappel est planifiée avec loop.call_soon().

L'argument nommé optionnel context permet de spécifier une classe contextvars.Context personnalisée dans laquelle la fonction de rappel s’exécutera. Le contexte actuel est utilisé si context n'est pas fourni.

functools.partial() peut être utilisée pour passer des paramètres à la fonction de rappel :

# Call 'print("Future:", fut)' when "fut" is done.
fut.add_done_callback(
    functools.partial(print, "Future:"))

Modifié dans la version 3.7: Ajout de l'argument nommé context. Voir PEP 567 pour plus de détails.

remove_done_callback(callback)

Retire callback de la liste de fonctions de rappel.

Renvoie le nombre de fonctions de rappel retiré. La méthode renvoie généralement 1, à moins que la fonction ait été ajoutée plus d'une fois.

cancel(msg=None)

Annule le Future et planifie l'exécution des fonctions de rappel.

Si le Future est déjà « terminé » ou « annulé », renvoie False. Autrement, change l'état du Future à « annulé », planifie l'exécution des fonctions de rappel et renvoie True.

Modifié dans la version 3.9: Ajout du paramètre msg.

exception()

Renvoie l'exception définie pour ce Future.

L'exception, ou None si aucune exception n'a été définie, est renvoyé seulement si le Future est « terminé ».

Si le Future a été annulé, cette méthode lève une exception CancelledError.

Si le Future n'est pas encore « terminé », cette méthode lève une exception InvalidStateError.

get_loop()

Renvoie la boucle d'évènements à laquelle le Future est attaché.

Nouveau dans la version 3.7.

Cet exemple crée un objet Future, puis crée et planifie l’exécution d'une tâche asynchrone qui définira le résultat du Future et attend jusqu'à ce que le Future ait un résultat :

async def set_after(fut, delay, value):
    # Sleep for *delay* seconds.
    await asyncio.sleep(delay)

    # Set *value* as a result of *fut* Future.
    fut.set_result(value)

async def main():
    # Get the current event loop.
    loop = asyncio.get_running_loop()

    # Create a new Future object.
    fut = loop.create_future()

    # Run "set_after()" coroutine in a parallel Task.
    # We are using the low-level "loop.create_task()" API here because
    # we already have a reference to the event loop at hand.
    # Otherwise we could have just used "asyncio.create_task()".
    loop.create_task(
        set_after(fut, 1, '... world'))

    print('hello ...')

    # Wait until *fut* has a result (1 second) and print it.
    print(await fut)

asyncio.run(main())

Important

L'objet Future est conçu pour imiter la classe concurrent.futures.Future. Les principales différences sont :