Lancer plusieurs consultations concurrentes
Objectif : Récupérer simultanément plusieurs taux de conversion pour les dépenses.
Une dépense peut être saisie dans une devise différente de celle utilisée pour établir un total. Si vous consultez les taux l’un après l’autre, chaque attente s’ajoute à la précédente et ralentit le traitement. Vous allez lancer plusieurs consultations en parallèle et réunir leurs résultats dans un seul dictionnaire.
La leçon précédente a présenté les coroutines et await pour attendre une opération d’entrée-sortie. Ici, asyncio.gather reçoit plusieurs appels de coroutines, les fait progresser concurremment et renvoie leurs résultats dans le même ordre que les appels fournis. Vous n’avez donc pas besoin de gérer vous-même l’association entre chaque devise et son taux.
Créer un collecteur de taux
Ajoutez le code suivant dans src/depenses/collecte.py. La fonction recuperer_taux reçoit une liste de codes de devises et une fonction asynchrone qui sait consulter un taux. Cette séparation permet de raccorder ensuite une source de taux réelle, tout en gardant l’exemple exécutable sans service externe.
import asyncio
from collections.abc import Awaitable, Callable
ConsultationTaux = Callable[[str], Awaitable[float]]
async def recuperer_taux(
devises: list[str],
consulter: ConsultationTaux,
) -> dict[str, float]:
"""Récupère concurremment un taux pour chaque devise."""
resultats = await asyncio.gather(
*(consulter(devise) for devise in devises)
)
return dict(zip(devises, resultats, strict=True))
async def consulter_taux_simule(devise: str) -> float:
"""Simule une consultation distante avec un délai d'attente."""
taux_simules = {
"USD": 0.92,
"GBP": 1.17,
"CHF": 1.04,
}
await asyncio.sleep(0.2)
return taux_simules[devise]
async def main() -> None:
devises = ["USD", "GBP", "CHF"]
taux = await recuperer_taux(devises, consulter_taux_simule)
for devise, valeur in taux.items():
print(f"{devise} : {valeur:.2f} EUR")
if __name__ == "__main__":
asyncio.run(main())USD : 0.92 EUR
GBP : 1.17 EUR
CHF : 1.04 EURLe type ConsultationTaux décrit la fonction attendue : elle reçoit un code de devise et renvoie un objet qu’une coroutine peut attendre pour obtenir un nombre décimal. Les annotations rendent ce contrat visible aux outils de vérification statique. Pour cet exemple, consulter_taux_simule attend brièvement avec asyncio.sleep, puis renvoie une valeur définie dans un dictionnaire local.
Dans recuperer_taux, l’expression génératrice construit un appel de consultation pour chaque devise. gather les attend ensemble : les trois attentes de 0,2 seconde se chevauchent, au lieu de s’additionner comme dans une boucle qui ferait un await complet avant de démarrer la consultation suivante. L’appel à dict associe ensuite chaque devise au résultat situé à la même position.
Exécuter et interpréter le résultat
Depuis la racine du projet, exécutez python -m depenses.collecte avec le dossier src dans le chemin des modules, ou utilisez votre configuration de développement habituelle pour ce paquet. Le programme affiche les trois taux. Le délai simulé de chaque consultation est de 0,2 seconde ; le délai total est donc proche de celui d’une seule consultation, auquel s’ajoute le temps de lancement, plutôt que de 0,6 seconde.
Cette réduction concerne le temps d’attente d’entrées-sorties indépendantes ; elle ne rend pas plus rapide un calcul intensif sur le processeur. Dans l’outil de dépenses, le collecteur pourra fournir plusieurs taux au traitement des montants sans que les consultations soient enchaînées. L’exemple ne contacte pas de service distant et ne fixe pas encore de limite au nombre de consultations simultanées.
À retenir
- Passez à asyncio.gather plusieurs appels de coroutines indépendantes pour les attendre concurremment.
- Les résultats sont renvoyés dans l’ordre des appels fournis, même si les consultations ne terminent pas dans cet ordre.
- Associez explicitement chaque résultat à sa devise et conservez des séquences de même longueur.
- La concurrence réduit l’attente d’entrées-sorties, mais ne constitue pas une optimisation du calcul sur le processeur.
La prochaine leçon ajoutera une limite au nombre de consultations simultanées afin de contrôler la charge envoyée à un service distant.