Introduction
cette bibliothèque standard dans la bibliothèque standard
Une bibliothèque stantard, c'est pas justement une bibliothèque dans la bibliothèque standard ?
C'est plus un effet de style qu'autre chose. Asyncio redéfinit beaucoup de choses qui sont déjà dans la bibliothèque standard pour les rendre asynchrones, comme asyncio.subprocess
, asyncio.sleep
. Ça la rend gloutonnique et c'est probablement la première chose qui choque quand on arrive sur sa doc. D'où la formulation "bibliothèque standard dans la bibliothèque standard".
avaient dessiné les contours avant elle : la programmation asynchrone.
Tu pourrais mettre en valeur "programmation asynchrone".
OK.
Mais enfin, à quoi ça sert ? Et comment ça marche ?
C'est un détail, mais peut-être qu'un bloc Question serait le bienvenu ici.
J'aime pas les blocs question quand la question est rhétorique ou à moitié rhétorique. C'est pour cette raison que je ne l'ai pas mise ici dan un bloc question. J'ai déjà mis un bloc information plus bas dans l'intro, et celui-ci casse bien le rythme (c'est l'effet escompté). Bref, je pense qu'il vaut mieux réserver ce bloc (à utiliser avec parcimonie) pour l'insérer dans le corps du texte, parce que sa première vocation est de réveiller le lecteur après un pavé.
Ça veut dire quoi, asynchrone ?
C'est parce qu'un vrai serveur fonctionne de façon asynchrone :
Encore un détail, mais j'ai un peu buté sur cette formulation. A priori, elle fait référence à "Il aurait l'air un peu idiot, non ?", qui n'est pas la dernière phrase.
OK je vais reformuler.
Concurrence et parallélisme
Mais pas en Python, ni dans aucun autre langage de la même famille que lui
Par curiosité, quelle est cette famille ?
Les langages "de script" (même si je déteste cette appellation réductrice). Qui sont haut niveau, exécutés par une machine virtuelle, typés dynamiquement, qui affranchissent le développeur de la gestion directe de la mémoire. J'hésitais à rajouter Perl dans l'énumération…
Où les interruptions sont prédictibles et explicites, donc tout le code entre deux interruptions est atomique,
Par "atomique", tu veux dire qui s'exécute d'un seul coup ? Il me semble intéressant d'expliciter ce terme.
OK je le ferai, j'y pensais en me relisant hier. Cela signifie effectivement que le code est exécuté d'un bloc, avec la garantie que l'opération ne sera pas interrompue.
Une boucle événementielle, c'est essentiel
En effet, tout l'intérêt de la programmation asynchrone est d'être capable d'occuper le programme pendant qu'une tâche donnée est en attente d'un événement.
Je ne crois pas que tu l'aies dit plus haut, donc il me semble important ici de faire le rapport avec yield
. Jusqu'à présent, tu as juste indiqué que ce mot-clé permettait de suspendre une coroutine, mais tu n'as pas lié ça à la notion d'IO.
C'est pas faux. Je me suis concentré sur la notion de concurrence sur cette partie, mais je m'aperçois que nulle part je ne dis que "dans la vraie vie, on ne fait jamais de yield
explicite avec asyncio
". Dans la précédente version de cet article j'avais une secion où on montrait que yield
pouvait être utilisé exactement comme un trap
pour faire une sorte d'appel système, ce qui rendait évident le fait que les IO passaient par là, mais je l'ai sucrée parce qu'elle rajoutait de la complexité à l'article pour pas grand chose. Il va donc falloir que je colle une ou deux phrases à ce sujet.
Dotons tout de même notre classe Loop d'une dernière méthode pour exécuter la boucle jusqu'à épuisement d'une coroutine en particulier :
Si j'ai bien compris, c'est équivalent à faire un schedule()
suivi d'un run_until_empty()
?
Le code suivant a-t-il un intérêt particulier ?
| >>> event_loop = Loop()
>>> event_loop.schedule(tic_tac())
>>> event_loop.run_until_complete(spam())
|
Oui, il lance les tâches tic_tac()
et spam()
en concurrence, et s'arrête quand spam()
a fini de travailler, même si tic_tac()
n'a pas fini.
Par contre, est-ce volontaire de ne plus parler des IO ? A partir du moment où on commence à coder, on manipule uniquement des tâches qu'on peut stopper, sans faire le parallèle avec les IO bloquantes que tu mentionnes dans les sections précédentes.
J'ai répondu plus haut. Je vais corriger ça. Le truc c'est que quand on commence à coder, on essaye déjà d'avoir un modèle de concurrence, sans s'occuper des IO, mais il faut vraiment que j'explique le rapport entre faire une IO et suspendre une tâche. J'espère juste trouver un moyen de le faire convenablement sans avoir à parler de select
.