web-dev-qa-db-fra.com

Une alternative propre et légère à Python's twisted?

Il y a longtemps que j'ai écrit un spider Web que j'ai multithread pour permettre à des requêtes simultanées de se produire en même temps. C'était dans mon Python jeunesse), quelques jours avant que je connaisse l'existence du [~ # ~] gil [~ # ~] et les malheurs associés au code multithread (IE, la plupart du temps, les choses finissent par être sérialisées!) ...

J'aimerais retravailler ce code pour le rendre plus robuste et plus performant. Pour ce faire, il existe essentiellement deux méthodes: utiliser le nouveau module de multitraitement dans la version 2.6+ ou opter pour un modèle basé sur un réacteur/événement de quelque sorte. Je préférerais faire cela plus tard, car c'est beaucoup plus simple et moins sujet aux erreurs.

La question se pose donc de savoir quel cadre conviendrait le mieux à mes besoins. Voici une liste des options que je connais jusqu'à présent:

  • Twisted : Le grand-père de Python cadres de réacteurs: semble complexe et un peu boursouflé cependant. Courbe d'apprentissage raide pour une petite tâche.
  • Eventlet : Parmi les gars de lindenlab . Cadre basé sur Greenlet conçu pour ce type de tâches. Cependant, j’ai jeté un coup d’œil au code et il n’est pas très joli: non conforme à pep8, parsemé de copies (pourquoi les gens font-ils cela dans un cadre!?), L’API semble un peu incohérente.
  • PyEv : Immature, il ne semble pas que quiconque l'utilise maintenant, bien qu'il soit basé sur libevent, de sorte qu'il dispose d'un backend solide.
  • asyncore : À partir de stdlib: über low level, semble être une lourde tâche de base pour réussir quelque chose.
  • tornade : Bien qu’il s’agisse d’un produit orienté serveur conçu pour les sites Web dynamiques, il dispose d’un client HTTP asynchrone et un simple ioloop . On dirait que cela pourrait faire le travail mais pas ce à quoi il était destiné. [edit: ne fonctionne malheureusement pas sous Windows, ce qui compte pour moi - c'est une exigence pour que je supporte cette plate-forme boiteuse]

Y a-t-il quelque chose que j'ai manqué du tout? Il doit sûrement y avoir une bibliothèque qui corresponde à la douceur d’une bibliothèque de réseau async simplifiée!

[edit: grand merci à intégré pour son pointeur sur cette page . Si vous faites défiler l'écran vers le bas, vous verrez qu'il y a vraiment une belle liste de projets qui visent à aborder cette tâche d'une manière ou d'une autre. Il semble en fait que les choses aient vraiment évolué depuis la création de Twisted: les gens semblent désormais préférer une solution co-routée plutôt qu’un réacteur traditionnel/callback orienté un. Les avantages de cette approche sont un code plus clair et plus direct: je l’ai certainement trouvé par le passé, en particulier lorsque je travaillais avec boost.asio en C++ basé sur le rappel Le code peut conduire à des conceptions difficiles à suivre et relativement obscures à l'œil non averti. L'utilisation de co-routines vous permet d'écrire du code qui a au moins l'air plus synchrone. Je suppose que ma tâche consiste maintenant à déterminer laquelle de ces nombreuses bibliothèques me plaît et à essayer! Content d'avoir demandé maintenant ...]

[edit: peut-être intéressant pour tous ceux qui ont suivi ou sont tombés sur cette question ou qui se soucient de ce sujet dans tous les sens du terme: j'ai trouvé un très bon résumé de l'état actuel des outils disponibles pour ce travail]

216
jkp

J'ai aimé le module concurrence Python qui repose sur Stackless Python microthreads ou Greenlets pour un threading léger. Tout réseau bloquant I/O est rendu transparent de manière asynchrone via une unique boucle libevent. Il devrait donc être presque aussi efficace qu'un serveur asynchrone réel.

Je suppose que cela ressemble à Eventlet de cette façon.

L'inconvénient est que son API est assez différente des modules sockets/threading de Python; vous devez réécrire une bonne partie de votre application (ou écrire un calque de compatibilité)

Edit: Il semble qu'il y ait aussi cogen , qui est similaire, mais utilise Python 2.5 générateurs améliorés pour ses coroutines, au lieu de Greenlets. Cela le rend plus portable que la concurrence et d'autres alternatives. Les E/S réseau se font directement avec epoll/kqueue/iocp.

27
intgr

Twisted est complexe, vous avez raison à ce sujet. Twisted est pas gonflé.

Si vous jetez un oeil ici: http://twistedmatrix.com/trac/browser/trunk/twisted vous trouverez une suite organisée, complète et très bien testée de de nombreux protocoles Internet, ainsi que du code d'assistance pour écrire et déployer des applications réseau très sophistiquées. Je ne confondrais pas la masse avec la globalité.

Il est bien connu que la documentation Twisted n’est pas la plus conviviale au premier abord, et j’estime que cela éloigne un nombre regrettable de personnes. Mais Twisted est incroyable (IMHO) si vous mettez le temps. C'est ce que j'ai fait et cela s'est avéré utile, et je recommanderais à d'autres d'essayer de la même manière.

98
clemesha

gevent est eventlet nettoyé .

En termes d'API, il respecte les mêmes conventions que la bibliothèque standard (en particulier, les modules de threading et de multitraitement). Donc, vous avez des choses familières comme file d'attente et événement pour travailler avec.

Il ne prend en charge que libevent ( update: libev depuis 1. ) en tant qu'implémentation de réacteur, mais en tire pleinement parti il comporte un serveur WSGI rapide basé sur libevent-http et résout les requêtes DNS via libevent-dns, au lieu d’utiliser un pool de threads comme le font la plupart des autres bibliothèques. ( update: depuis 1.0, c-ares est utilisé pour créer des requêtes DNS asynchrones; le pool de threads est également une option.)

Comme eventlet, il rend les rappels et les différés inutiles en utilisant greenlets .

Découvrez les exemples: téléchargement simultané de plusieurs URL , discussion en ligne prolongée .

56
Denis Bilenko

Une très comparaison intéressante de tels frameworks a été compilée par Nicholas Piël sur son blog: ça vaut vraiment la peine d'être lu!

27
jkp

Aucune de ces solutions n'évitera le fait que la GIL empêche le parallélisme de la CPU - ce sont simplement de meilleurs moyens d'obtenir un parallélisme IO déjà existant avec les threads. Si vous pensez pouvoir faire mieux, tous les moyens sont utiles, mais si votre goulot d’étranglement est dans le traitement des résultats, rien ici ne vous aidera, à l’exception du module de multitraitement.

15
Adam Hupp

Je n’irais pas jusqu’à appeler Twisted ballonné, mais c’est difficile de passer à autre chose. J'ai assez longtemps évité de m'initier à l'apprentissage, car je voulais toujours quelque chose d'un peu plus facile pour les "petites tâches".

Cependant, maintenant que je travaille encore un peu plus, je dois dire que le fait de disposer de toutes les piles incluses est TRÈS agréable.

Toutes les autres bibliothèques asynchrones avec lesquelles j'ai travaillé sont bien moins matures qu'elles ne le paraissent. La boucle d'événements de Twisted est solide.

Je ne sais pas trop comment résoudre la courbe d'apprentissage abrupte de Twisted. Cela aiderait peut-être si quelqu'un le faisait et nettoyait quelques choses, comme supprimer tous les problèmes de compatibilité ascendante et les projets morts. Mais c'est la nature d'un logiciel mature, je suppose.

11
rhettg

Kamaelia n'a pas encore été mentionné. Son modèle de concurrence repose sur le câblage de composants avec des messages échangés entre les boîtes de réception et les boîtes d'envoi. Ici un bref aperçu.

8
Steven Kryskalla

J'ai commencé à utiliser tordu pour certaines choses. La beauté de la chose est presque parce qu'elle est "gonflée". Il existe des connecteurs pour presque tous les principaux protocoles. Vous pouvez avoir un bot Jabber qui prend des commandes et les poste sur un serveur irc, les envoie par courrier électronique à quelqu'un, exécute une commande, lit à partir d'un serveur NNTP et surveille les modifications d'une page Web. La mauvaise nouvelle est qu’il peut faire tout cela et rendre les choses trop complexes pour des tâches simples telles que celle décrite par le PO. L’avantage de python est que vous n'incluez que ce dont vous avez besoin. Ainsi, même si le téléchargement peut prendre 20 Mo, vous ne pouvez inclure que 2 Mo de bibliothèques (ce qui est encore beaucoup). Bien qu’ils incluent des exemples, tout ce qui est au-delà d’un serveur TCP de base ne dépend que de vous.

Bien que ce ne soit pas une solution python, j’ai vu récemment que node.js gagnait beaucoup plus en traction. En fait, j’ai envisagé d’envisager des projets plus petits, mais j’éprouve un sentiment de recul. javascript :)

7
vrillusions

Il existe un bon livre sur le sujet: "Twisted Network Programming Essentials" de Abe Fettig. Les exemples montrent comment écrire du code très Pythonic, et pour moi personnellement, ne me paraissez pas comme basé sur un framework gonflé. Regardez les solutions dans le livre, si elles ne sont pas propres, alors je ne sais pas ce que signifie "propre".

Mon seul Enigma est le même que j'ai avec d'autres cadres, comme Ruby. Je m'inquiète, est-ce que ça grandit? Je détesterais engager un client dans un framework qui va avoir des problèmes d'évolutivité.

4
mrsmoothie

Whizzer est un petit framework de socket asynchrone utilisant pyev. C'est très rapide, principalement à cause de pyev. Il tente de fournir une interface similaire à celle tordue avec quelques légères modifications.

4
bfrog

Essayez aussi Syncless . C'est basé sur la coroutine (donc similaire à Concurrence, Eventlet et gevent). Il implémente des remplacements instantanés non bloquants pour socket.socket, socket.gethostbyname (etc.), ssl.SSLSocket, time.sleep et select.select. C'est rapide. Il faut Stackless Python et libevent. Il contient une extension Python obligatoire écrite en C (Pyrex/Cython).

2
pts

Je confirme le bien de syncless. Il peut utiliser libev (la version plus récente, plus propre et plus performante de libevent). Il y a quelques temps, il n’a pas autant de soutien que libevent, mais le processus de développement va maintenant plus loin et est très utile.

2
Robert Zaremba

Si vous voulez juste une bibliothèque de requêtes HTTP légère et simplifiée, alors je trouve nirest vraiment bien

1
ejectamenta

Nous vous invitons à jeter un coup d’œil sur PyWorks, qui adopte une approche très différente. Il permet aux instances d'objet de s'exécuter dans leur propre thread et rend les appels de fonction à cet objet asynchrones.

Laissez simplement une classe hériter de Task au lieu d’objet et c’est asynchrone, tous les appels de méthodes sont des mandataires. Les valeurs renvoyées (si vous en avez besoin) sont des mandataires futurs.

res = obj.method( args )
# code continues here without waiting for method to finish
do_something_else( )
print "Result = %d" % res # Code will block here, if res not calculated yet

PyWorks peut être trouvé sur http://bitbucket.org/raindog/pyworks

0
renejsum