Programmation Asynchrone
La programmation asynchrone est un paradigme dans lequel un programme peut continuer à exécuter d’autres tâches pendant qu’une opération longue est en cours, sans attendre qu’elle se termine.
Elle repose sur des mécanismes non bloquants, souvent utiles pour les opérations d’entrée/sortie (I/O) comme les appels réseau, accès disque ou calculs externes.
Objectif
-
Optimiser l’utilisation des ressources : éviter que le programme ne reste inactif pendant une attente.
-
Améliorer la réactivité : traiter plus de requêtes en moins de temps.
-
Scalabilité : meilleure gestion d’un grand nombre de connexions simultanées.
Principe de fonctionnement
-
Synchrone : chaque tâche attend la fin de la précédente avant de démarrer.
-
Asynchrone : une tâche peut être mise en attente (await), et d’autres s’exécutent en parallèle sur le même thread.
Avantages
-
Réactivité accrue : idéal pour serveurs web recevant beaucoup de requêtes.
-
Moins de threads/processus nécessaires → économie de mémoire.
-
Adapté aux I/O lourds (accès API, lecture disque, requêtes BDD).
Limites
-
Plus complexe à écrire et à déboguer.
-
Pas toujours plus rapide pour des calculs CPU intensifs (dans ce cas, privilégier multi-processus).
-
Nécessite un framework compatible (FastAPI, Node.js, asyncio…).
Applications typiques
-
Serveurs web à forte charge (FastAPI, Node.js, Tornado).
-
Chatbots et assistants IA temps réel.
-
Applications de streaming (vidéo/audio).
-
Automatisation de tâches réseau (scraping, monitoring).
Outils & frameworks en Python
-
asyncio
: module standard pour l’asynchrone. -
FastAPI : API asynchrone performante.
-
aiohttp : requêtes HTTP asynchrones.
-
SQLAlchemy async : accès BDD non bloquant.
Fonctions :
-
Programmation Asynchrone (exemple)
Importation :
import asyncio import random
Exemple de code :
import asyncio import random # Fonction asynchrone simulant une tâche longue async def task(name, duration): print(f"{name} commence, durée prévue : {duration} secondes") await asyncio.sleep(duration) # Pause asynchrone print(f"{name} terminée après {duration} secondes") return f"{name} résultat" # Fonction principale qui exécute plusieurs tâches en parallèle async def main(): # Création de plusieurs tâches avec des durées aléatoires tasks = [ asyncio.create_task(task("Tâche 1", random.randint(1, 5))), asyncio.create_task(task("Tâche 2", random.randint(1, 5))), asyncio.create_task(task("Tâche 3", random.randint(1, 5))), ] # Attente de la fin de toutes les tâches results = await asyncio.gather(*tasks) print("Tous les résultats :", results) # Lancement de la boucle asynchrone asyncio.run(main())
Explication du code :
import asyncio
importe le module asyncio, qui permet d’exécuter des opérations asynchrones et de gérer une boucle d’événements.import random
importe le module random pour générer des nombres aléatoires, ici utilisés pour simuler des durées de tâches variables.Définir une fonction asynchrone
async def task(name, duration):
crée une fonction asynchrone nommée task qui prend un nom et une durée.
await asyncio.sleep(duration)
suspend la fonction pendantduration
secondes de manière non bloquante, permettant à d’autres tâches de s’exécuter en parallèle.
return f"{name} résultat"
renvoie un résultat après la fin de la tâche.Définir la fonction principale asynchrone
async def main():
crée la fonction principale où l’on va exécuter plusieurs tâches en parallèle.
tasks = [asyncio.create_task(task(...)), ...]
crée une liste de tâches asynchrones avec create_task(), ce qui permet de les planifier pour exécution simultanée.
results = await asyncio.gather(*tasks)
attend la fin de toutes les tâches et récupère leurs résultats sous forme de liste.
print("Tous les résultats :", results)
affiche les résultats lorsque toutes les tâches sont terminées.Lancer la boucle asynchrone
asyncio.run(main())
démarre la boucle d’événements et exécute la fonction asynchrone main() jusqu’à ce qu’elle soit terminée.