@ -44,19 +44,19 @@ Si votre application (d'une certaine maniĂšre) n'a pas Ă communiquer avec une a
---
Si vous ne savez pas, utilisez se uleme nt `def` .
Si vous ne savez pas, utilisez un `def` normal .
---
Note : vous pouvez mĂ©langer `def` et `async def` dans vos *fonctions de chemin d'accĂšs* autant que nĂ©cessaire, et dĂ©finir chacune avec lâoption la plus adaptĂ©e pour vous. FastAPI fera ce qu'il faut avec elles.
**Remarque** : vous pouvez mĂ©langer `def` et `async def` dans vos *fonctions de chemin d'accĂšs* autant que nĂ©cessaire, et dĂ©finir chacune avec lâoption la plus adaptĂ©e pour vous. FastAPI fera ce qu'il faut avec elles.
Au final, peu importe le cas parmi ceux ci-dessus, FastAPI fonctionnera de maniĂšre asynchrone et sera extrĂȘmement rapide.
Mais si vous suivez bien les instruction s ci-dessus, il pourra effectuer quelques optimisations et ainsi améliorer les performances .
Mais si vous suivez bien les étape s ci-dessus, il pourra effectuer quelques optimisations d e performance.
## Détails techniques { #technical -details }
Les versions modernes de Python supportent le **code asynchrone** grùce aux ** « coroutines »** avec les syntaxes ** `async` et `await` **.
Les versions modernes de Python supportent le ** « code asynchrone »** en utilisant quelque chose appelé ** « coroutines »**, avec la syntaxe ** `async` et `await` **.
Analysons les différentes parties de cette phrase dans les sections suivantes :
@ -70,7 +70,7 @@ Faire du code asynchrone signifie que le langage đŹ est capable de dire Ă l'o
Donc, pendant ce temps, l'ordinateur pourra effectuer d'autres tĂąches, pendant que « slow-file » đ se termine.
Ensuite l'ordinateur / le programme đ€ reviendra Ă chaque fois qu'il en a la chance que ce soit parce qu'il attend Ă nouveau, ou car il đ€ a fini tout le travail qu'il avait Ă faire. Il đ€ regardera donc si les tĂąches qu'il attend ont terminĂ© d'ĂȘtre effectuĂ©es .
Ensuite l'ordinateur / le programme đ€ reviendra Ă chaque fois qu'il en a la chance, parce qu'il attend Ă nouveau, ou quand il đ€ a fini tout le travail qu'il avait Ă faire Ă ce moment-lĂ . Et il đ€ regardera si des tĂąches qu'il attendait ont dĂ©jĂ terminĂ©, en faisant ce qu'il devait faire .
Ensuite, il đ€ prendra la premiĂšre tĂąche Ă finir (disons, notre « slow-file » đ) et continuera Ă faire avec cette derniĂšre ce qu'il Ă©tait censĂ©.
@ -80,18 +80,18 @@ Ce « attendre quelque chose d'autre » fait généralement référence à des o
* de la donnée envoyée depuis votre programme soit reçue par le client à travers le réseau
* le contenu d'un fichier sur le disque soit lu par le systÚme et passé à votre programme
* le contenu que votre programme a passé au systÚme soit écrit sur le disque
* une opération effectuée à distance par une API se termine
* une opération effectuée à distance par une API
* une opération en base de données se termine
* une requĂȘte Ă une base de donnĂ©es renvoie un rĂ©sultat
* etc.
Le temps d'exécution étant consommé majoritairement par l'attente d'opérations < abbr title = "Input and Output - Entrées et sorties" > I/O< / abbr > , on appelle ceci des opérations « I/O bound ».
Ce concept se nomme « asynchrone » car l'ordinateur / le programme n'a pas besoin d'ĂȘtre « synchronisĂ© » avec la tĂąche, attendant le moment exact oĂč cette derniĂšre se terminera en ne faisant rien, pour ĂȘtre capable de rĂ©cupĂ©rer le rĂ©sultat de la tĂąche et l'utiliser dans la suite des opĂ©rations.
Ce concept se nomme « asynchrone » car l'ordinateur / le programme n'a pas besoin d'ĂȘtre « synchronisĂ© » avec la tĂąche lente , attendant le moment exact oĂč cette derniĂšre se terminera en ne faisant rien, pour ĂȘtre capable de rĂ©cupĂ©rer le rĂ©sultat de la tĂąche et l'utiliser dans la suite des opĂ©rations.
à la place, en étant « asynchrone », une fois terminée, une tùche peut légÚrement attendr e (quelques microsecondes) que l'ordinateur / le programme finisse ce qu'il était en train de faire, et revienne récupérer le résultat .
à la place, en étant un systÚme « asynchrone », une fois terminée, la tùche peut attendre un peu dans la fil e (quelques microsecondes) que l'ordinateur / le programme finisse ce qu'il était en train de faire, puis revienne récupérer les résultats et continue à travailler avec eux .
Pour parler de tĂąches « synchrones » (en opposition à « asynchrones »), on utilise souvent le terme « sĂ©quentiel », car l'ordinateur / le programme va effectuer toutes les Ă©tapes d'une tĂąche sĂ©quentiellement avant de passer Ă une autre tĂąche, mĂȘme si ces Ă©tapes impliquent de l'attente.
Pour parler de tĂąches « synchrones » (en opposition à « asynchrones »), on utilise souvent aussi le terme « sĂ©quentiel », car l'ordinateur / le programme va effectuer toutes les Ă©tapes d'une tĂąche sĂ©quentiellement avant de passer Ă une autre tĂąche, mĂȘme si ces Ă©tapes impliquent de l'attente.
### Concurrence et Burgers { #concurrency -and-burgers }
@ -99,49 +99,49 @@ L'idée de code **asynchrone** décrite ci-dessus est parfois aussi appelée **
La **concurrence** et le **parallĂ©lisme** sont tous deux liĂ©s Ă l'idĂ©e de « diffĂ©rentes choses arrivant plus ou moins au mĂȘme moment ».
Mais les détails entre la **concurrence** et le **parallélisme** diffÚrent sur de nombreux poi nts.
Mais les détails entre la *concurrence* et le *parallélisme* sont assez différe nts.
Pour expliquer la différence, voici une histoire de burgers :
Pour expliquer la différence, imaginez l'histoire suivante à propos de burgers :
### Burgers concurrents { #concurrent -burgers }
Vous amenez votre crush đ dans votre fast food đ favori, et faites la queue pendant que le serveur đ prend les commandes des personnes devant vous.
Vous allez avec votre crush chercher de la nourriture dans un fast food, vous faites la queue pendant que le caissier prend les commandes des personnes devant vous. đ
< img src = "/img/async/concurrent-burgers/concurrent-burgers-01.png" class = "illustration" >
Puis vient votre tour, vous commandez alors 2 magnifiques burgers đ pour votre crush đ et vous.
Puis vient votre tour, vous commandez alors 2 burgers trĂšs sophistiquĂ©s pour votre crush et vous. đđ
< img src = "/img/async/concurrent-burgers/concurrent-burgers-02.png" class = "illustration" >
Le serveur đ dit quelque chose Ă son collĂšgue dans la cuisine đšâđł pour qu'il sache qu'il doit prĂ©parer vos burgers đ (bien qu'il soit dĂ©jĂ en train de prĂ©parer ceux des clients prĂ©cĂ©dents).
Le caissier dit quelque chose au cuisinier dans la cuisine pour qu'il sache qu'il doit préparer vos burgers (bien qu'il soit déjà en train de préparer ceux des clients précédents).
< img src = "/img/async/concurrent-burgers/concurrent-burgers-03.png" class = "illustration" >
Vous payez đž.
Vous payez. đž
Le serveur đ vous donne le numĂ©ro assignĂ© Ă votre commande .
Le caissier vous donne le numéro de votre tour .
< img src = "/img/async/concurrent-burgers/concurrent-burgers-04.png" class = "illustration" >
Pendant que vous attendez, vous allez choisir une table avec votre crush đ, vous discutez avec votre crush đ pendant un long moment (les burgers Ă©tant « magnifiques » ils sont trĂšs longs Ă prĂ©parer âšđâš ).
Pendant que vous attendez, vous allez choisir une table avec votre crush, vous vous asseyez et discutez avec votre crush pendant un long moment (vos burgers étant trÚs sophistiqués, ils prennent du temps à préparer ).
Pendant que vous ĂȘtes assis Ă table, en attendant que les burgers đ soient prĂȘt s, vous pouvez passer ce temps Ă admirer Ă quel point votre crush đ est gĂ©niale, mignonne et intelligente âšđâš.
Pendant que vous ĂȘtes assis Ă table avec votre crush , en attendant les burgers, vous pouvez passer ce temps Ă admirer Ă quel point votre crush est gĂ©niale, mignonne et intelligente âšđâš.
< img src = "/img/async/concurrent-burgers/concurrent-burgers-05.png" class = "illustration" >
Pendant que vous discutez avec votre crush đ , de temps en temps vous jetez un coup dâĆil au nombre affichĂ© au-dessus du comptoir pour savoir si c'est Ă votre tour d'ĂȘtre servis .
Pendant que vous attendez et discutez avec votre crush, de temps en temps, vous jetez un coup dâĆil au nombre affichĂ© au-dessus du comptoir pour savoir si c'est dĂ©j Ă votre tour.
Jusqu'au moment oĂč c'est (enfin) votre tour. Vous allez au comptoir, rĂ©cupĂ©rez vos burgers đ et revenez Ă votre table.
Puis, à un moment, c'est enfin votre tour. Vous allez au comptoir, récupérez vos burgers et revenez à votre table.
< img src = "/img/async/concurrent-burgers/concurrent-burgers-06.png" class = "illustration" >
Vous et votre crush đ mangez les burgers đ et passez un bon moment âš.
Vous et votre crush mangez les burgers et passez un bon moment. âš
< img src = "/img/async/concurrent-burgers/concurrent-burgers-07.png" class = "illustration" >
/// note | Remarque
Illustrations proposĂ©e s par [Ketrina Thompson ](https://www.instagram.com/ketrinadrawsalot ). đš
Belles illustration s par [Ketrina Thompson ](https://www.instagram.com/ketrinadrawsalot ). đš
///
@ -149,103 +149,103 @@ Illustrations proposées par [Ketrina Thompson](https://www.instagram.com/ketrin
Imaginez que vous ĂȘtes l'ordinateur / le programme đ€ dans cette histoire.
Pendant que vous faites la queue, vous ĂȘtr e simplement inactif đŽ, attendant votre tour, ne faisant rien de « productif ». Mais la queue est rapide car le serveur đ prend seulement les commandes (et ne les prĂ©pare pas), donc tout va bien.
Pendant que vous faites la queue, vous ĂȘtes simplement inactif đŽ, attendant votre tour, ne faisant rien de trĂšs « productif ». Mais la queue est rapide car le cai ssi er prend seulement les commandes (et ne les prĂ©pare pas), donc tout va bien.
Ensuite, quand c'est votre tour, vous faites des actions « productives » đ€, vous Ă©tudiez le menu, dĂ©cidez ce que vous voulez, demandez Ă votre crush đ son choix, payez đž, vĂ©rifiez que vous utilisez la bonne carte de crĂ©dit, vĂ©rifiez que le montant dĂ©bitĂ© sur la carte est correct, vĂ©rifiez que la commande contient les bons produits, etc.
Ensuite, quand c'est votre tour, vous faites du vrai travail « productif », vous étudiez le menu, décidez ce que vous voulez, demandez à votre crush son choix, payez, vérifiez que vous donnez le bon billet ou la bonne carte, vérifiez que le montant débité est correct, vérifiez que la commande contient les bons produits, etc.
Mais ensuite, mĂȘme si vous n'avez pas encore vos burgers đ , votre travail avec le serveur đ est « en pause » âž, car vous devez attendre đ que vos burgers soient prĂȘts.
Mais ensuite, mĂȘme si vous n'avez toujours pas vos burgers, votre travail avec le cai ssi er est « en pause » âž, car vous devez attendre đ que vos burgers soient prĂȘts.
AprĂšs vous ĂȘtre Ă©cartĂ© du comptoir et vous ĂȘtre assis Ă votre table avec le numĂ©ro de votre commande , vous pouvez tourner đ votre attention vers votre crush đ , et « travailler » ⯠đ€ lĂ -dessus. Vous ĂȘtes donc Ă nouveau en train de faire quelque chose de « productif » đ€, vous flirtez avec votre crush đ.
Mais lorsque vous vous Ă©cartez du comptoir et vous asseyez Ă table avec un numĂ©ro pour votre tour , vous pouvez tourner đ votre attention vers votre crush, et « travailler » ⯠đ€ lĂ -dessus. Vous ĂȘtes donc Ă nouveau en train de faire quelque chose de trĂšs « productif », comme flirter avec votre crush đ.
Puis le serveur đ dit « J'ai fini de prĂ©parer les burgers » đ en mettant votre numĂ©ro sur l'affichage du comptoir, mais vous ne courez pas immĂ©diatement au moment oĂč votre numĂ©ro s'affiche. Vous savez que personne ne volera vos burgers đ car vous avez votre numĂ©ro et les autres client s ont le leur.
Puis le caissier đ dit « J'ai fini de faire les burgers » en mettant votre numĂ©ro sur l'affichage du comptoir, mais vous ne sautez pas comme un fou immĂ©diatement quand le numĂ©ro affichĂ© change pour devenir votre numĂ©ro. Vous savez que personne ne volera vos burgers car vous avez le numĂ©ro de votre tour, et les autre s ont le leur.
Vous attendez donc que votre crush đ finisse son histoire, souriez gentiment et dites que vous allez chercher les burgers âž.
Vous attendez donc que votre crush finisse son histoire (termine le travail actuel ⯠/ la tĂąche en cours de traitement đ€) , souriez gentiment et dites que vous allez chercher les burgers âž.
Pour finir vous allez au comptoir đ, vers la tĂąche initiale qui est dĂ©sormais terminĂ©e âŻ, rĂ©cupĂ©rez les burgers đ , remerciez le serveur et ramenez les burgers đ Ă votre table. Ceci termine l'Ă©tape / la tĂąche d'interaction avec le comptoir âč. Ce qui ensuite, crĂ©e une nouvelle tĂąche de « manger les burgers » đ âŻ, mais la prĂ©cĂ©dente, « rĂ©cupĂ©rer les burgers » est terminĂ©e âč.
Puis vous allez au comptoir đ, vers la tĂąche initiale qui est dĂ©sormais terminĂ©e âŻ, rĂ©cupĂ©rez les burgers, remerciez et ramenez les burgers Ă votre table. Ceci termine l'Ă©tape / la tĂąche d'interaction avec le comptoir âč. Ce qui ensuite crĂ©e une nouvelle tĂąche, « manger les burgers » đ âŻ, mais la prĂ©cĂ©dente, « rĂ©cupĂ©rer les burgers », est terminĂ©e âč.
### Burgers parallĂšles { #parallel -burgers }
Imaginons désormais que ce ne sont pas des « burgers concurrents » mais des « b urgers parallÚles ».
Imaginons désormais que ce ne sont pas des « Burgers concurrents » mais des « B urgers parallÚles ».
Vous allez avec votre crush đ dans un fast food đ parallĂ©lisĂ© .
Vous allez avec votre crush chercher de la nourriture dans un fast food parallĂšle .
Vous attendez pendant que plusieurs (disons 8) serveurs qui sont aussi des cuisiniers đšâđłđšâđłđšâđłđšâđłđšâđłđšâđłđšâđłđšâđł prennent les commandes des personnes devant vous.
Vous attendez pendant que plusieurs (disons 8) caissiers qui sont en mĂȘme temps cuisiniers prennent les commandes des personnes devant vous.
Chaque personne devant vous attend đ que son burger đ soit prĂȘt avant de quitter le comptoir car chacun des 8 serveu rs va lui-mĂȘme prĂ©parer le burger directement avant de prendre la commande suivante.
Chaque personne devant vous attend que son burger soit prĂȘt avant de quitter le comptoir car chacun des 8 cai ssi ers va prĂ©parer le burger directement avant de prendre la commande suivante.
< img src = "/img/async/parallel-burgers/parallel-burgers-01.png" class = "illustration" >
Puis c'est enfin votre tour, vous commandez 2 magnifiques burgers đ pour vous et votre crush đ .
Puis c'est enfin votre tour, vous commandez 2 burgers trÚs sophistiqués pour vous et votre crush .
Vous payez đž.
< img src = "/img/async/parallel-burgers/parallel-burgers-02.png" class = "illustration" >
Le serveu r va dans la cuisine đšâđł .
Le cai ssi er va dans la cuisine.
Vous attendez devant le comptoir afin que personne ne prenne vos burgers đ avant vous, vu qu'il n'y a pas de numĂ©ro de commande .
Vous attendez, debout devant le comptoir đ, afin que personne d'autre ne prenne vos burgers avant vous, vu qu'il n'y a pas de numĂ©ros pour les tours .
< img src = "/img/async/parallel-burgers/parallel-burgers-03.png" class = "illustration" >
Vous et votre crush đ Ă©tant occupĂ©s Ă vĂ©rifier que personne ne passe devant vous prendre vos burgers au moment oĂč ils arriveront đ, vous ne pouvez pas vous prĂ©occuper de votre crush đ.
Vous et votre crush Ă©tant occupĂ©s Ă ne laisser personne passer devant vous et prendre vos burgers au moment oĂč ils arriveront, vous ne pouvez pas prĂȘter attention Ă votre crush. đ
C'est du travail « synchrone », vous ĂȘtre « synchronisĂ©s » avec le serveu r/cuisinier đšâđł. Vous devez attendre đ et ĂȘtre prĂ©sent au moment exact oĂč le serveur/cuisinier đšâđł finira les burgers đ et vous les donnera, sinon quelqu'un risque de vous les prendre.
C'est du travail « synchrone », vous ĂȘtre « synchronisĂ©s » avec le cai ssi er/cuisinier đšâđł. Vous devez attendre đ et ĂȘtre prĂ©sent au moment exact oĂč le caissier/cuisinier đšâđł finira les burgers et vous les donnera, sinon quelqu'un d'autre risque de vous les prendre.
< img src = "/img/async/parallel-burgers/parallel-burgers-04.png" class = "illustration" >
Puis le serveu r/cuisinier đšâđł revient enfin avec vos burgers đ , aprĂšs un long moment d'attente đ devant le comptoir.
Puis votre caissie r/cuisinier đšâđł revient enfin avec vos burgers, aprĂšs un long moment d'attente đ devant le comptoir.
< img src = "/img/async/parallel-burgers/parallel-burgers-05.png" class = "illustration" >
Vous prenez vos burgers đ et allez Ă une table avec votre crush đ
Vous prenez vos burgers et allez Ă une table avec votre crush.
Vous les mangez, et vous avez terminĂ© đ âč.
Vous les mangez simplement, et vous avez terminĂ©. âč
< img src = "/img/async/parallel-burgers/parallel-burgers-06.png" class = "illustration" >
Durant tout ce processus, il n'y a presque pas eu de discussions ou de flirts car la plupart de votre temps Ă Ă©tĂ© passĂ© Ă attendre đ devant le comptoir đ.
Il n'y a pas eu beaucoup de discussions ou de flirts car la plupart du temps a Ă©tĂ© passĂ© Ă attendre đ devant le comptoir. đ
/// note | Remarque
Illustrations proposĂ©e s par [Ketrina Thompson ](https://www.instagram.com/ketrinadrawsalot ). đš
Belles illustration s par [Ketrina Thompson ](https://www.instagram.com/ketrinadrawsalot ). đš
///
---
Dans ce scĂ©nario de burgers parallĂšles, vous ĂȘtes un ordinateur / programme đ€ avec deux processeurs (vous et votre crush đ) attendant đ Ă deux et dĂ©diant votre attention ⯠à « attendre devant le comptoir » đ pour une longue durĂ©e.
Dans ce scĂ©nario de burgers parallĂšles, vous ĂȘtes un ordinateur / programme đ€ avec deux processeurs (vous et votre crush), tous deux attendant đ et dĂ©diant leur attention ⯠à « attendre devant le comptoir » đ pour une longue durĂ©e.
Le fast-food a 8 processeurs (serveurs/cuisiniers) đšâđłđšâđłđšâđłđšâđłđšâđłđšâđłđšâđłđšâđł. Alors que le fast-food de burgers concurrents en avait 2 (un serveu r et un cuisinier).
Le fast food a 8 processeurs (caissiers/cuisiniers). Alors que le fast food de burgers concurrents aurait pu n'en avoir que 2 (un caissie r et un cuisinier).
Et pourtant l'expĂ©rience finale n'est pas meilleure đ.
Mais tout de mĂȘme, l'expĂ©rience finale n'est pas la meilleure. đ
---
C' est donc l'histoire Ă©quivalente parallĂšle pour les burgers đ.
Ce serai t donc l'histoire Ă©quivalente parallĂšle pour les burgers. đ
Pour un exemple plus courant dans la « vie réelle », imaginez une banque.
Pour un exemple plus « vie réelle », imaginez une banque.
Jusqu'Ă rĂ©cemment, la plupart des banques avaient plusieurs caisses (et banqu iers) đšâđŒđšâđŒđšâđŒđšâđŒ et une uniqu e file d'attente đđđđđđđđ.
Jusqu'Ă rĂ©cemment, la plupart des banques avaient plusieurs caissiers đšâđŒđšâđŒđšâđŒđšâđŒ et une grand e file d'attente đđđđđđđđ.
Tous les banquiers faisaient l'intĂ©gralitĂ© du travail avec chaque client avant de passer au suivant đšâđŒâŻ.
Tous les caissiers faisaient tout le travail avec chaque client avant de passer au suivant đšâđŒâŻ.
Et vous devi ez attendre đ dans la file pendant un long moment ou vous perdiez votre place .
Et vous devez attendre đ dans la file pendant un long moment ou vous perdez votre tour .
Vous n'auriez donc probablement pas envie d'amener votre crush đ avec vous Ă la banque đŠ.
Vous n'auriez donc probablement pas envie d'amener votre crush đ avec vous pour faire des dĂ©marches Ă la banque đŠ.
### Conclusion sur les burgers { #burger -conclusion }
Dans ce scĂ©nario des « burgers du fast-food avec votre crush », comme il y a beaucoup d'attente đ, il est trĂš s logique d'avoir un systĂšme concurrent âžđâŻ.
Dans ce scĂ©nario des « burgers de fast food avec votre crush », comme il y a beaucoup d'attente đ, il est beaucoup plu s logique d'avoir un systĂšme concurrent âžđâŻ.
Et c 'est le cas pour la plupart des applications web.
C 'est le cas pour la plupart des applications web.
Vous aurez de nombreux, nombreux utilisateurs, mais votre serveur attendra đ que leur connexion peu performante envoie de s requĂȘtes.
De trĂšs, trĂšs nombreux utilisateurs, mais votre serveur attend đ que leur connexion pas trĂšs bonne envoie leur s requĂȘtes.
Puis vous attendrez đ de nouveau que leur s rĂ©ponses reviennent.
Puis attend đ de nouveau que les rĂ©ponses reviennent.
Cette « attente » đ se mesure en microsecondes, mais tout de mĂȘme, en cumulĂ© cela fait beaucoup d'attente .
Cette « attente » đ se mesure en microsecondes, mais tout de mĂȘme, en les cumulant toutes, cela fait beaucoup d'attente au final .
C'est pourquoi il est logique d'utiliser du code asynchrone âžđ⯠pour des APIs web.
C'est pourquoi il est trĂšs logique d'utiliser du code asynchrone âžđ⯠pour des APIs web.
Ce type d'asynchronicité est ce qui a rendu NodeJS populaire (bien que NodeJS ne soit pas parallÚle) et c'est la force de Go en tant que langage de programmation.
@ -255,11 +255,11 @@ Et comme on peut avoir du parallĂ©lisme et de l'asynchronicitĂ© en mĂȘme temps,
### Est-ce que la concurrence est mieux que le parallélisme ? { #is -concurrency-better-than-parallelism }
Nope ! C'est ça la morale de l'histoire.
Nope ! Ce n'est pas la morale de l'histoire.
La concurrence est différente du parallélisme. C'est mieux sur des scénarios **spécifiques** qui impliquent beaucoup d'attente. à cause de ça, c'est généralement bien meilleur que le parallélisme pour le développement d'applications web. Mais pas pour tout.
La concurrence est différente du parallélisme. Et c'est mieux dans des scénarios **spécifiques** qui impliquent beaucoup d'attente. à cause de ça, c'est généralement bien meilleur que le parallélisme pour le développement d'applications web. Mais pas pour tout.
Donc pour équilibrer tout ça, imaginez l'histoire suivante :
Donc pour équilibrer tout ça, imaginez l'histoire courte suivante :
> Vous devez nettoyer une grande et sale maison.
@ -269,42 +269,42 @@ Donc pour équilibrer tout ça, imaginez l'histoire suivante :
Il n'y a plus d'attente đ nulle part, juste beaucoup de travail Ă effectuer, dans diffĂ©rentes piĂšces de la maison.
Vous pourriez diviser en diffĂ©rentes sections comme avec les burgers, d'abord le salon, puis la cuisine, etc. Mais vous n'attendez đ rien, vous ne faites que nettoyer et nettoyer, la sĂ©paration en sections ne changerait rien au final .
Vous pourriez avoir des tours comme dans l'exemple des burgers, d'abord le salon, puis la cuisine, mais comme vous n'attendez đ rien, vous ne faites que nettoyer et nettoyer, les tours ne changeraient rien .
Cela prendrait autant de temps pour finir avec ou sans section s (concurrence) et vous auriez effectuĂ© la mĂȘme quantitĂ© de travail.
Cela prendrait autant de temps pour finir avec ou sans tour s (concurrence) et vous auriez effectuĂ© la mĂȘme quantitĂ© de travail.
Mais dans ce cas, si pouviez amener 8 ex-serveurs/cuisiniers/devenus-nettoyeurs đšâđłđšâđłđšâđłđšâđłđšâđłđšâđłđšâđłđšâđł , et que chacun d'eux (plus vous) pouvait prendre une zone de la maison pour la nettoyer, vous pourriez faire tout le travail en parallĂšle, et finir plus tĂŽt.
Mais dans ce cas, si vous pouviez amener les 8 ex-caissiers/cuisiniers/désormais-nettoyeurs , et que chacun d'eux (plus vous) pouvait prendre une zone de la maison pour la nettoyer, vous pourriez faire tout le travail en ** parallÚle** , avec l'aide supplémentaire , et finir beaucoup plus tÎt.
Dans ce scénario, chacun des nettoyeurs (vous y compris) serait un processeur, faisant sa partie du travail.
Et comme la plupart du temps d'exécution est pris par du « vrai » travail (et non de l'attente), et que le travail dans un ordinateur est fait par un < abbr title = "Central Processing Unit - Unité centrale de traitement" > CPU< / abbr > , ce sont des problÚmes dits « CPU bound ».
Et comme la plupart du temps d'exécution est pris par du vrai travail (et non de l'attente), et que le travail dans un ordinateur est fait par un < abbr title = "Central Processing Unit - Unité centrale de traitement" > CPU< / abbr > , ce sont des problÚmes dits « CPU bound ».
---
Des exemples communs d'opérations « CPU bound » sont les procédé s qui requiÚrent des traitements mathématiques complexes.
Des exemples communs d'opérations CPU bound sont les chose s qui requiÚrent des traitements mathématiques complexes.
Par exemple :
* Traitements d'**audio** et d'**images**.
* La **vision par ordinateur ** : une image est composĂ©e de millions de pixels, chaque pixel ayant 3 valeurs / couleurs, les traiter tous va nĂ©cessiter d'effectuer des traitements sur chaque pixel, et de prĂ©fĂ©rence tous en mĂȘme temps.
* L'apprentissage automatique (ou **Machine Learning** ) : cela nĂ©cessite de nombreuses multiplications de matrices et vecteurs. Imaginez une Ă©norme feuille de calcul remplie de nombres que vous multiplierez entre eux tous au mĂȘme moment.
* L'apprentissage profond (ou **Deep Learning** ) : est un sous-domaine du **Machine Learning** , donc les mĂȘmes raisons s'appliquent. Avec la diffĂ©renc e qu'il n'y a pas une unique feuille de calcul de nombres Ă multiplier, mais une Ă©norme quantitĂ© d'entre elles, et dans de nombreux cas, on utilise un processeur spĂ©cial pour construire et / ou utiliser ces modĂšles.
* Traitements d'**audio** ou d'**images**.
* **Computer vision** : une image est composĂ©e de millions de pixels, chaque pixel ayant 3 valeurs / couleurs, les traiter nĂ©cessite normalement d'effectuer des calculs sur ces pixels, tous en mĂȘme temps.
* **Machine Learning** : cela nĂ©cessite normalement de nombreuses multiplications de « matrices » et de « vecteurs » . Imaginez une Ă©norme feuille de calcul remplie de nombres et les multiplier tous ensemble au mĂȘme moment.
* **Deep Learning** : c'est un sous-domaine du Machine Learning, donc les mĂȘmes raisons s'appliquent. C'est just e qu'il n'y a pas une unique feuille de calcul de nombres Ă multiplier, mais une Ă©norme quantitĂ© d'entre elles, et dans de nombreux cas, on utilise un processeur spĂ©cial pour construire et / ou utiliser ces modĂšles.
### Concurrence + Parallélisme : Web + Machine Learning { #concurrency -parallelism-web-machine-learning }
Avec **FastAPI** vous pouvez bénéficier de la concurrence qui est trÚs courante en développement web (c'est l' attrait principal de NodeJS).
Avec **FastAPI** vous pouvez bĂ©nĂ©ficier de la concurrence qui est trĂšs courante en dĂ©veloppement web (le mĂȘme attrait principal de NodeJS).
Mais vous pouvez aussi profiter du parallélisme et du multiprocessing (plusieurs processus s'exécutant en parallÚle) afin de gérer des charges **CPU bound** qui sont récurrentes dans les systÚmes de *Machine Learning* .
Mais vous pouvez aussi profiter du parallélisme et du multiprocessing (plusieurs processus s'exécutant en parallÚle) afin de gérer des charges **CPU bound** comme celles des systÚmes de Machine Learning .
Ăa, ajoutĂ© au fait que Python soit le langage le plus populaire pour la **Data Science** , le **Machine Learning** et surtout le **Deep Learning** , font de **FastAPI** un trĂšs bon choix pour les APIs et applications de **Data Science** / **Machine Learning** .
Ăa, ajoutĂ© au simple fait que Python soit le langage principal pour la **Data Science** , le Machine Learning et surtout le Deep Learning, fait de FastAPI un trĂšs bon choix pour les APIs web et applications de Data Science / Machine Learning (entre autres) .
Pour comprendre comment mettre en place ce parallélisme en production, allez lire la section [Déploiement ](deployment/index.md ).
Pour comprendre comment mettre en place ce parallélisme en production, consultez la section sur le [Déploiement ](deployment/index.md ).
## `async` et `await` { #async -and-await }
Les versions modernes de Python ont une maniÚre trÚs intuitive de définir le code asynchrone, tout en gardant une apparence de code « séquentiel » classique en laissant Python faire l'attente pour vous au bon moment .
Les versions modernes de Python ont une maniÚre trÚs intuitive de définir le code asynchrone. Cela le fait ressembler à du code « séquentiel » normal et effectue l'« attente » pour vous aux bons moments .
Pour une opération qui nécessite de l'attente avant de donner un résultat et qui supporte ces nouvelles fonctionnalités Python, vous pouvez l'utiliser comme tel :
Pour une opération qui nécessite de l'attente avant de donner un résultat et qui supporte ces nouvelles fonctionnalités Python, vous pouvez l'écrire comme ceci :
```Python
burgers = await get_burgers(2)
@ -312,7 +312,7 @@ burgers = await get_burgers(2)
Le mot-clĂ© important ici est `await` . Il informe Python qu'il faut attendre âž que `get_burgers(2)` finisse d'effectuer ses opĂ©rations đ avant de stocker les rĂ©sultats dans la variable `burgers` . GrĂące Ă cela, Python saura qu'il peut aller effectuer d'autres opĂ©rations đ ⯠pendant ce temps (comme par exemple recevoir une autre requĂȘte).
Pour que `await` fonctionne, il doit ĂȘtre placĂ© dans une fonction qui supporte l' asynchronicitĂ©. Pour que ça soit le cas, il faut dĂ©clarer cette derniĂšre avec `async def` :
Pour que `await` fonctionne, il doit ĂȘtre placĂ© dans une fonction qui supporte cette asynchronicitĂ©. Pour que ça soit le cas, il faut dĂ©clarer cette derniĂšre avec `async def` :
```Python hl_lines="1"
async def get_burgers(number: int):
@ -320,7 +320,7 @@ async def get_burgers(number: int):
return burgers
```
... et non `def` :
... au lieu de `def` :
```Python hl_lines="2"
# Ceci n'est pas asynchrone
@ -331,16 +331,16 @@ def get_sequential_burgers(number: int):
Avec `async def` , Python sait que dans cette fonction il doit prendre en compte les expressions `await` , et qu'il peut mettre en pause âž l'exĂ©cution de la fonction pour aller faire autre chose đ avant de revenir.
Pour appeler une fonction définie avec `async def` , vous devez utiliser `await` . Donc ceci ne marche pas :
Lorsque vous voulez appeler une fonction `async def` , vous devez l'« attendre » . Donc ceci ne marche pas :
```Python
# Ceci ne fonctionne pas, car get_burgers a été défini avec async def
# Ceci ne fonctionne pas, car get_burgers a été défini avec : async def
burgers = get_burgers(2)
```
---
Donc, si vous utilisez une bibliothÚque qui nécessite que ses fonctions soient appelées avec `await` , vous devez définir la *fonction de chemin d'accÚs* en utilisant `async def` comme dans :
Donc, si vous utilisez une bibliothÚque qui vous indique que vous pouvez l'appeler avec `await` , vous devez créer les *fonctions de chemin d'accÚs* qui l'utilisent avec `async def` , comme dans :
```Python hl_lines="2-3"
@app .get('/burgers')
@ -351,13 +351,13 @@ async def read_burgers():
### Plus de détails techniques { #more -technical-details }
Vous avez donc compris que `await` peut seulement ĂȘtre utilisĂ© dans des fonctions dĂ©finies avec `async def` .
Vous avez peut-ĂȘtre remarquĂ© que `await` peut seulement ĂȘtre utilisĂ© dans des fonctions dĂ©finies avec `async def` .
Mais en mĂȘme temps, les fonctions dĂ©finies avec `async def` doivent ĂȘtre appelĂ©es avec `await` et donc dans des fonctions dĂ©finies elles aussi avec `async def` .
Mais en mĂȘme temps, les fonctions dĂ©finies avec `async def` doivent ĂȘtre « attendues ». Donc, les fonctions avec `async def` peuvent seulement ĂȘtre appelĂ©es Ă l'intĂ©rieur de fonctions dĂ©finies elles aussi avec `async def` .
Vous avez donc remarquĂ© ce paradoxe d 'Ćuf et de la poule, comment appelle-t-on la premiĂšre fonction `async` ?
Donc, Ă propos de l 'Ćuf et de la poule, comment appelle-t-on la premiĂšre fonction `async` ?
Si vous utilisez **FastAPI** , pas besoin de vous en inquiéter, car cette « premiÚre » fonction sera votre *fonction de chemin d'accÚs* ; et **FastAPI** saura comment arriver au résultat attendu .
Si vous utilisez **FastAPI** , pas besoin de vous en inquiéter, car cette « premiÚre » fonction sera votre *fonction de chemin d'accÚs* , et FastAPI saura comment faire ce qu'il faut .
Mais si vous souhaitez utiliser `async` / `await` sans FastAPI, vous pouvez également le faire.
@ -367,7 +367,7 @@ Starlette (et **FastAPI**) sâappuie sur [AnyIO](https://anyio.readthedocs.io/e
En particulier, vous pouvez utiliser directement [AnyIO ](https://anyio.readthedocs.io/en/stable/ ) pour vos cas dâusage de concurrence avancĂ©s qui nĂ©cessitent des schĂ©mas plus Ă©laborĂ©s dans votre propre code.
Et mĂȘme si vous nâutilisiez pas FastAPI, vous pourriez aussi Ă©crire vos propres applications async avec [AnyIO ](https://anyio.readthedocs.io/en/stable/ ) pour une grande compatibilitĂ© et pour bĂ©nĂ©ficier de ses avantages (par ex. la « structured concurrency » ).
Et mĂȘme si vous nâutilisiez pas FastAPI, vous pourriez aussi Ă©crire vos propres applications async avec [AnyIO ](https://anyio.readthedocs.io/en/stable/ ) pour une grande compatibilitĂ© et pour bĂ©nĂ©ficier de ses avantages (par ex. la *structured concurrency* ).
Jâai créé une autre bibliothĂšque au-dessus dâAnyIO, comme une fine surcouche, pour amĂ©liorer un peu les annotations de type et obtenir une meilleure **autocomplĂ©tion** , des **erreurs en ligne** , etc. Elle propose Ă©galement une introduction et un tutoriel accessibles pour vous aider Ă **comprendre** et Ă©crire **votre propre code async** : [Asyncer ](https://asyncer.tiangolo.com/ ). Elle sera particuliĂšrement utile si vous devez **combiner du code async avec du code classique** (bloquant/synchrone).
@ -377,25 +377,25 @@ L'utilisation d'`async` et `await` est relativement nouvelle dans ce langage.
Mais cela rend la programmation asynchrone bien plus simple.
Cette mĂȘme syntaxe (ou presque) a aussi Ă©tĂ© incluse rĂ©cemment dans les versions modernes de JavaScript (dans les navigateurs et NodeJS).
Cette mĂȘme syntaxe (ou presque) a aussi Ă©tĂ© incluse rĂ©cemment dans les versions modernes de JavaScript (dans le navigateur et NodeJS).
Mais avant ça, gérer du code asynchrone était bien plus complexe et difficile.
Dans les versions précédentes de Python, vous auriez utilisé des threads ou [Gevent ](https://www.gevent.org/ ). Mais le code aurait été bien plus difficile à comprendre, débugger, et concevoir.
Dans les versions précédentes de Python, vous auriez pu utiliser des threads ou [Gevent ](https://www.gevent.org/ ). Mais le code est bien plus difficile à comprendre, débugger, et concevoir.
Dans les versions précédentes de JavaScript cÎté navigateur / NodeJS, vous auriez utilisé des « callbacks ». Menant potentiellement à ce que l'on appelle le « callback hell ».
Dans les versions précédentes de NodeJS / JavaScript de navigateur, vous auriez utilisé des « callbacks ». Ce qui mÚne au « callback hell ».
## Coroutines { #coroutines }
« Coroutine » est juste un terme Ă©laborĂ© pour dĂ©signer ce qui est retournĂ© par une fonction dĂ©finie avec `async def` . Python sait que c'est comme une fonction classique qui va dĂ©marrer Ă un moment et terminer Ă un autre, mais qu'elle peut aussi ĂȘtre mise en pause âž, du moment qu'il y a un `await` dans son contenu .
**Coroutine** est juste un terme Ă©laborĂ© pour dĂ©signer ce qui est retournĂ© par une fonction dĂ©finie avec `async def` . Python sait que c'est comme une fonction, qui peut dĂ©marrer et qui se terminera Ă un moment, mais qu'elle peut aussi ĂȘtre mise en pause âž en interne, quand il y a un `await` Ă l'intĂ©rieur .
Mais toutes ces fonctionnalités d'utilisation de code asynchrone avec `async` et `await` sont souvent résumées comme l'utilisation des « coroutines ». On peut comparer cela à la principale fonctionnalité clé de Go, les « Goroutines ».
## Conclusion { #conclusion }
Reprenons la phrase du début de la page :
Reprenons la mĂȘme phrase ci-dessus :
> Les versions modernes de Python supportent le **code asynchrone** grùce aux ** « coroutines »** avec les syntaxes ** `async` et `await` **.
> Les versions modernes de Python supportent le ** « code asynchrone »** en utilisant quelque chose appelé ** « coroutines »**, avec la syntaxe ** `async` et `await` **.
Ceci devrait ĂȘtre plus comprĂ©hensible dĂ©sormais. âš
@ -409,25 +409,25 @@ Vous pouvez probablement ignorer cela.
Ce sont des détails trÚs poussés sur comment **FastAPI** fonctionne en arriÚre-plan.
Si vous avez de bonnes connaissances techniques (coroutines, threads, code bloquant, etc.) et ĂȘtes curieux de comment ** FastAPI** gĂšre `async def` versus le `def` classique, cette partie est faite pour vous.
Si vous avez de bonnes connaissances techniques (coroutines, threads, code bloquant, etc.) et ĂȘtes curieux de comment FastAPI gĂšre `async def` versus le `def` classique, cette partie est faite pour vous.
///
### Fonctions de chemin d'accĂšs { #path -operation-functions }
Quand vous dĂ©clarez une *fonction de chemin d'accĂšs* avec un `def` normal et non `async def` , elle est exĂ©cutĂ©e dans un groupe d e threads (thread pool) externe qui est ensuite attendu, plutĂŽt que d'ĂȘtre appelĂ©e directement (car cela bloquerait le serveur).
Quand vous dĂ©clarez une *fonction de chemin d'accĂšs* avec un `def` normal et non `async def` , elle est exĂ©cutĂ©e dans une threadpool externe qui est ensuite attendue , plutĂŽt que d'ĂȘtre appelĂ©e directement (car cela bloquerait le serveur).
Si vous venez d'un autre framework asynchrone qui ne fonctionne pas comme de la façon dĂ©crite ci-dessus et que vous ĂȘtes habituĂ© Ă dĂ©finir des *fonctions de chemin d'accĂšs* basiques et purement calculatoires avec un simple `def` pour un faible gain de performance (environ 100 nanosecondes), veuillez noter que dans **FastAPI** , l'effet serait plutĂŽt contraire. Dans ces cas-lĂ , il vaut mieux utiliser `async def` Ă moins que votre *fonction de chemin d'accĂšs* utilise du code qui effectue des opĂ©rations < abbr title = "Input/Output - EntrĂ©es/Sorties: lecture ou Ă©criture sur le disque, communications rĂ©seau." > I/O</ abbr > bloquantes.
Si vous venez d'un autre framework async qui ne fonctionne pas de la façon dĂ©crite ci-dessus et que vous ĂȘtes habituĂ© Ă dĂ©finir des *fonctions de chemin d'accĂšs* triviales faisant uniquement du calcul avec un simple `def` pour un faible gain de performance (environ 100 nanosecondes), veuillez noter que dans **FastAPI** , l'effet serait plutĂŽt contraire. Dans ces cas-lĂ , il vaut mieux utiliser `async def` Ă moins que vos *fonctions de chemin d'accĂšs* utilisent du code qui effectue des opĂ©rations < abbr title = "Input/Output - EntrĂ©es/Sorties: lecture ou Ă©criture sur le disque, communications rĂ©seau." > I/O</ abbr > bloquantes.
Au final, dans les deux situations, il est fort probable que **FastAPI** soit tout de mĂȘme [plus rapide ](index.md#performance ) que (ou au moins de vitesse Ă©ga le Ă ) votre framework prĂ©cĂ©dent.
Au final, dans les deux situations, il est fort probable que **FastAPI** soit [tout de mĂȘme plus rapide ](index.md#performance ) que (ou au moins comparab le Ă ) votre framework prĂ©cĂ©dent.
### Dépendances { #dependencies }
La mĂȘme chose s'applique aux [dĂ©pendances ](tutorial/dependencies/index.md ). Si une dĂ©pendance est dĂ©finie avec `def` plutĂŽt que `async def` , elle est exĂ©cutĂ©e dans la threadpool externe.
La mĂȘme chose s'applique aux [dĂ©pendances ](tutorial/dependencies/index.md ). Si une dĂ©pendance est une fonction standard `def` plutĂŽt qu'`async def` , elle est exĂ©cutĂ©e dans la threadpool externe.
### Sous-dépendances { #sub -dependencies }
Vous pouvez avoir de multiples dĂ©pendances et [sous-dĂ©pendances ](tutorial/dependencies/sub-dependencies.md ) dĂ©pendant les unes des autres (en tant que paramĂštres de la dĂ©finition de la *fonction de chemin d'accĂšs* ), certaines créées avec `async def` et d'autres avec `def` . Cela fonctionnerait aussi, et celles dĂ©finies avec un simple `def` seraient exĂ©cut Ă©es sur un thread externe (venant de la threadpool) plutĂŽt que d'ĂȘtre « attendues ».
Vous pouvez avoir de multiples dĂ©pendances et [sous-dĂ©pendances ](tutorial/dependencies/sub-dependencies.md ) dĂ©pendant les unes des autres (en tant que paramĂštres des dĂ©finitions des fonctions ), certaines créées avec `async def` et d'autres avec un `def` normal . Cela fonctionnerait aussi, et celles dĂ©finies avec un `def` normal seraient appel Ă©es sur un thread externe (venant de la threadpool) plutĂŽt que d'ĂȘtre « attendues ».
### Autres fonctions utilitaires { #other -utility-functions }
@ -435,10 +435,10 @@ Toute autre fonction utilitaire que vous appelez directement peut ĂȘtre créée
Contrairement aux fonctions que FastAPI appelle pour vous : les *fonctions de chemin d'accÚs* et dépendances.
Si votre fonction utilitaire est une fonction classique définie avec `def` , elle sera appelée directement (telle qu'écrite dans votre code), pas dans une threadpool ; si la fonction est définie avec `async def` alors vous devrez attendre (avec `await` ) que cette fonction se termine avant de passer à la suite du code.
Si votre fonction utilitaire est une fonction classique définie avec `def` , elle sera appelée directement (telle qu'écrite dans votre code), pas dans une threadpool ; si la fonction est définie avec `async def` alors vous devez `await` cette fonction lorsque vous l'appelez dans votre code.
---
Encore une fois, ce sont des dĂ©tails trĂšs techniques qui peuvent ĂȘtre utiles si vous venez ici les chercher.
Sinon, les instructions de la section < a href = "#in-a-hurry" > Vous ĂȘtes pressĂ©s ?< / a > ci-dessus sont largement suffisantes .
Sinon, les instructions de la section ci-dessus sont largement suffisantes : < a href = "#in-a-hurry" > Vous ĂȘtes pressĂ©s ?< / a > .