web-dev-qa-db-fra.com

Quelle est la différence fondamentale entre asyncio et trio?

Aujourd'hui, j'ai trouvé une bibliothèque nommée trio qui dit être une API asynchrone pour les humains. Ces mots sont un peu similaires avec requests '. Comme requests est vraiment une bonne bibliothèque, je me demande quels sont les avantages de trio.

Il n'y a pas beaucoup d'articles à ce sujet, je viens de trouver un article discutant curio et asyncio. À ma grande surprise, trio se dit même mieux que curio (nouvelle génération).

Après avoir lu la moitié de l'article, je ne trouve pas la différence fondamentale entre ces deux cadres asynchrones. Il donne juste quelques exemples que l'implémentation de curio est plus pratique que celle de asyncio. Mais la structure sous-jacente est presque la même (basée sur les rappels, je pense que tous les cadres IO asynchrones sont basés sur des rappels sans aucune exception.)

Alors quelqu'un pourrait-il me donner une raison pour laquelle je dois accepter que trio ou curio soit meilleur que asyncio? Ou expliquer davantage pourquoi je devrais choisir trio au lieu de asyncio intégré?

37
Sraw

D'où je viens: Je suis l'auteur principal du trio. Je suis également l'un des principaux contributeurs de curio (et j'ai écrit l'article à ce sujet auquel vous associez un lien), ainsi qu'un développeur Python) qui a activement participé aux discussions sur la manière d'améliorer l'asyncio.

Je ne suis pas sûr de ce que vous entendez par rappel. En trio (et curio), l’un des principes fondamentaux de la conception est que vous ne programmez jamais avec des rappels; cela ressemble plus à une programmation basée sur des threads qu'à une programmation basée sur le rappel. Je suppose que si vous ouvrez le capot et regardez comment elles sont mises en œuvre à l'interne, il y a des endroits où ils utilisent des rappels, ou des choses qui sont en quelque sorte équivalentes aux rappels si vous plissez les yeux. Mais c’est comme dire que Python et C sont équivalents car l’interprète Python est implémenté en C. You n'utilisez jamais de rappels.

En tous cas:

Trio vs asyncio

Asyncio est plus mature

La première grande différence est la maturité de l'écosystème. Au moment où j'écris ceci en mars 2018 , il y a beaucoup de bibliothèques supplémentaires avec le support asyncio que le soutien de trio. Par exemple, il n’existe actuellement aucun serveur HTTP réel prenant en charge le trio. Le classificateur Framework :: AsyncIO sur PyPI contient actuellement 122 bibliothèques, tandis que le classificateur Framework :: Trio n'en a que 8. J'espère que cette partie de la réponse deviendra rapidement obsolète - par exemple, voici Kenneth Reitz expérimentant l’ajout du support du trio dans la prochaine version des requêtes - mais pour le moment, vous devez vous attendre à ce que si vous êtes un trio pour quelque chose de compliqué, alors vous rencontrerez des éléments manquants que vous devez remplir vous-même au lieu de récupérer une bibliothèque de pypi, ou que vous devrez utiliser le package trio-asyncio qui vous permet d'utiliser des bibliothèques asyncio dans des programmes trio =. (Le canal de discussion en trio est utile pour savoir ce qui est disponible et ce sur quoi les autres personnes travaillent.)

Trio simplifie votre code

En ce qui concerne les bibliothèques réelles, elles sont également très différentes. L’argument principal du trio est qu’il est beaucoup plus simple d’écrire du code concurrent que d’utiliser asyncio. Bien sûr, quand avez-vous entendu dire pour la dernière fois que leur bibliothèque rend les choses plus difficiles à utiliser ... laissez-moi vous donner un exemple concret. Dans this talk ( Slides (diapositives) ), j'utilise l'exemple de la mise en œuvre RFC 8305 "Happy eyeballs" , qui est un algorithme simultané simple utilisé de manière efficace. établir une connexion réseau. C'est quelque chose auquel Glyph réfléchit depuis des années et sa dernière version pour Twisted compte environ 600 lignes. (Asyncio serait à peu près le même; Twisted et asyncio sont très similaires d’un point de vue architectural.) Dans l’exposé, je vous enseigne tout ce que vous devez savoir pour l’implémenter sur <40 lignes à l’aide de trio (et nous corrigeons un bogue dans sa version alors re à cela). Ainsi, dans cet exemple, l’utilisation du trio simplifie littéralement notre code.

Vous pourriez également trouver ces commentaires des utilisateurs intéressants: 1 , 2 ,

Il y a beaucoup de différences dans les détails

Pourquoi cela arrive-t-il? C'est une réponse beaucoup plus longue :-). Je travaille progressivement à la rédaction des différents articles dans les articles de blogues et les exposés, et je vais essayer de ne pas oublier de mettre à jour cette réponse avec des liens dès qu'ils sont disponibles. Fondamentalement, Trio dispose d’un petit groupe de primitives soigneusement conçues, qui présentent quelques différences fondamentales par rapport à toute autre bibliothèque que je connaisse (bien que, bien sûr, développant des idées de nombreux endroits). Voici quelques notes aléatoires pour vous donner une idée:

Un problème très très courant en asyncio et dans les bibliothèques associées est que vous appelez some_function(), et le résultat est renvoyé. Vous pensez donc que c'est fait - mais en réalité, il fonctionne toujours en arrière-plan. Cela conduit à toutes sortes de bugs complexes, car il est difficile de contrôler l’ordre dans lequel les choses se passent, ou de savoir quand quelque chose est réellement terminé, et cela peut directement masquer les problèmes car si une tâche d’arrière-plan se bloque avec une exception non gérée, asyncio généralement, il suffit d'imprimer quelque chose sur la console, puis de continuer. En trio, la façon dont nous gérons la création de tâches via des "nurseries" signifie qu'aucune de ces choses ne se produit: lorsqu'une fonction est retournée, vous savez que c'est fait et que Trio est actuellement la seule bibliothèque de concurrence pour Python où les exceptions se propagent toujours jusqu'à ce que vous les attrapiez.

La façon de Trio de gérer les délais d'attente et les annulations est nouvelle et je pense qu'elle est meilleure que les systèmes à la pointe de la technologie tels que C # et Golang. j'ai en fait écrit un essai complet sur ce sujet donc je n'entrerai pas dans tous les détails ici. Mais le système d'annulation d'asyncio - ou en réalité, les systèmes, il en a deux avec une sémantique légèrement différente - sont basés sur un ensemble d'idées plus ancien que même C # et Golang, et sont difficiles à utiliser correctement. (Par exemple, il est facile pour un code "d'échapper" accidentellement à une annulation en générant une tâche en arrière-plan; voir le paragraphe précédent.)

Il y a une tonne de choses redondantes en asyncio, qui peut rendre difficile de dire quelle chose utiliser quand . Vous avez des avenirs, des tâches et des coroutines, qui sont tous essentiellement utilisés dans le même but, mais vous devez connaître les différences qui les séparent. Si vous souhaitez implémenter un protocole réseau, vous devez choisir d'utiliser la couche protocoles/transports ou la couche streams, et ils ont tous les deux des pièges complexes (c'est ce que la première partie de l'essai que vous avez lié = est sur le point).

Actuellement, Trio est la seule bibliothèque d'accès simultané pour Python où control-C fonctionne comme vous le souhaitez (c'est-à-dire qu'il soulève KeyboardInterrupt où que votre code soit). C'est une petite chose , mais cela fait une grande différence :-). Pour diverses raisons, je ne pense pas que ce soit réparable en asyncio.

En résumé

Si vous avez besoin d'expédier quelque chose en production la semaine prochaine, vous devriez alors utiliser asyncio (ou Twisted ou Tornado ou gevent, qui sont encore plus matures). Ils ont de grands écosystèmes, d'autres personnes les ont déjà utilisés pour la production et ils ne vont nulle part.

Si vous essayez d'utiliser ces frameworks vous laisse frustré et confus, ou si vous voulez expérimenter une manière différente de faire les choses, alors jetez un œil à notre trio - nous sommes sympathiques :-).

Si vous souhaitez expédier quelque chose en production dans un an… je ne sais pas trop quoi vous dire. Python est en mutation. Trio présente de nombreux avantages au niveau de la conception, mais cela suffit-il pour dépasser la longueur d'avance de l'asyncio? L'asyncio figurant dans la bibliothèque standard sera-t-il un avantage ou un inconvénient? ( Remarquez comment de nos jours tout le monde utilise requests, même si la bibliothèque standard a rllib .) Combien de nouvelles idées du trio peuvent être ajoutées à asyncio? Personne ne le sait. Il y aura beaucoup de discussions intéressantes à ce sujet à PyCon cette année :-).

83
Nathaniel J. Smith