5.2Programmation asynchrone (asyncio)
Quand un programme passe son temps à attendre (réponses réseau, base de données, fichiers), la programmation asynchrone permet de faire autre chose pendant l'attente, au lieu de rester bloqué. Avec async/await et le module asyncio, un seul programme peut gérer des milliers de tâches d'attente simultanément.
C'est une notion avancée qui déroute au début, car elle change la façon de raisonner. Elle est au cœur des serveurs web modernes performants (FastAPI) et de tout ce qui manipule beaucoup d'entrées/sorties. On distingue bien ce cas des tâches gourmandes en calcul, qui relèvent d'autres outils.
Vocabulaire de la section
- Programmation asynchrone
- Modèle où le programme n'attend pas passivement : il passe à d'autres tâches pendant les temps morts (I/O).
- async / await
- async définit une coroutine ; await met en pause en attendant un résultat, libérant le programme pour d'autres tâches.
- asyncio
- Module standard qui orchestre l'exécution des coroutines via une boucle d'événements.
- Coroutine
- Fonction asynchrone (async def) pouvant être suspendue et reprise, gérée par la boucle d'événements.
- I/O-bound vs CPU-bound
- I/O-bound = limité par l'attente (réseau, disque) → asyncio ; CPU-bound = limité par le calcul → multiprocessing.
Dans quel cas la programmation asynchrone (asyncio) apporte-t-elle un gain ?
En pratique — Découvrir async/await avec asyncio
- Écrivez une coroutine « async def tache(n) » qui affiche un message, attend (await asyncio.sleep(1)) puis affiche la fin.
- Lancez-la avec asyncio.run() et observez le comportement séquentiel d'une seule tâche.
- Lancez plusieurs tâches EN PARALLÈLE avec asyncio.gather() : constatez que 3 attentes d'1 s prennent ~1 s au total, pas 3.
- Concluez : l'asynchrone brille quand on ATTEND (réseau, I/O), pas pour accélérer un calcul intensif.
Points clés à retenir
- L'asynchrone occupe le programme pendant les temps d'attente au lieu de le bloquer.
- async définit une coroutine ; await met en pause en attendant un résultat.
- asyncio.gather() lance plusieurs tâches d'attente en parallèle.
- asyncio sert les cas I/O-bound (réseau, disque), pas les calculs intensifs (→ multiprocessing).
Questions fréquentes
Asynchrone, threads, multiprocessing : quelle différence ?
asyncio gère la concurrence d'attentes I/O dans un seul thread (idéal réseau/disque). Le threading partage aussi un processus mais convient à certains I/O bloquants. Le multiprocessing lance plusieurs processus pour paralléliser du CALCUL sur plusieurs cœurs. On choisit selon que le goulot est l'attente (asyncio) ou le calcul (multiprocessing).
L'asynchrone rend-il forcément un programme plus rapide ?
Non. Il accélère les charges dominées par l'attente (beaucoup de requêtes réseau simultanées). Pour un calcul pur (CPU-bound), il n'apporte rien, voire complique inutilement le code. Utilisez-le à bon escient, là où il y a des temps morts à exploiter.