Aller au contenu principal

Mélanger code synchrone et asynchrone

Dans un projet réel on doit souvent :

  • Appeler du code async depuis du code classique
  • Exécuter du code bloquant (lib, CPU) sans bloquer la loop

Entrée principale : asyncio.run()

Toujours utilisé une seule fois au point d'entrée du programme.

# main.py
import asyncio

async def logique():
return 42

if __name__ == "__main__":
resultat = asyncio.run(logique())
print(resultat)

Éviter d'appeler asyncio.run() depuis une coroutine déjà en cours (erreur).

Appeler async depuis sync (hors main)

Lorsqu'on décide d'utiliser asyncio, il est préférable de propager l'asynchronicité jusqu'au sommet de la pile d'appels. Il est en effet compliqué et source d'erreurs de vouloir encapsuler de l'async dans du sync. Cela est possible avec asyncio.run() si aucune loop n'est active.

import asyncio

async def tache_async(x):
await asyncio.sleep(1)
return x * 2

def version_sync(*args, **kwargs):
return asyncio.run(tache_async(*args, **kwargs)) # bloque jusqu’au résultat

# usage
res = version_sync(42)
print(res)

Si jamais une loop est active (ex: dans un serveur web async), asyncio.run() lève une RuntimeError. Dans ce cas, il faut repenser l'architecture pour propager l'asynchronicité, ou utiliser un autre thread pour faire l'appel avec asyncio.run() sur ce thread.