Vor (langer) Zeit habe ich einen Web-Spider geschrieben, den ich multithreaded habe, damit gleichzeitig Anfragen auftreten können. Das war in meiner Python-Jugend, in den Tagen, bevor ich über die GIL und die damit verbundenen Probleme für Multithread-Code Bescheid wusste (IE, die meisten Dinge werden nur serialisiert!) ...
Ich möchte diesen Code überarbeiten, um ihn robuster und leistungsfähiger zu machen. Grundsätzlich gibt es zwei Möglichkeiten, dies zu tun: Ich könnte das neue Multiprocessing-Modul in 2.6+ verwenden oder mich für ein reaktor- / ereignisbasiertes Modell entscheiden. Ich würde das lieber später machen, da es viel einfacher und weniger fehleranfällig ist.
Die Frage bezieht sich also darauf, welcher Rahmen am besten zu meinen Bedürfnissen passt. Das Folgende ist eine Liste der Optionen, die ich bisher kenne:
- Twisted : Der Urvater der Python-Reaktor-Frameworks: scheint jedoch komplex und etwas aufgebläht zu sein. Steile Lernkurve für eine kleine Aufgabe.
- Eventlet : Von den Jungs von Lindenlab . Greenlet-basiertes Framework, das auf diese Art von Aufgaben ausgerichtet ist. Ich habe mir den Code angesehen und er ist nicht allzu hübsch: Nicht pep8-konform, mit Drucken übersät (warum machen die Leute das in einem Framework!?), Scheint die API ein wenig inkonsistent zu sein.
- PyEv : Unreif , scheint momentan niemand zu sein, der es benutzt, obwohl es auf libevent basiert, also hat es ein solides Backend.
- asyncore : Aus der stdlib: über low-level, scheint eine Menge Beinarbeit zu sein, nur um etwas in Gang zu bringen.
- tornado : Obwohl dies ein serverorientiertes Produkt ist, das für die Serverung dynamischer Websites entwickelt wurde, verfügt es über einen asynchronen HTTP-Client und einen einfachen ioloop . Sieht so aus, als könnte es die Arbeit erledigen, aber nicht das, wofür es gedacht war. [edit: läuft leider nicht unter Windows, was für mich zählt - es ist eine Voraussetzung für mich, diese lahme Plattform zu unterstützen]
Gibt es etwas, das ich überhaupt vermisst habe? Sicherlich muss es da draußen eine Bibliothek geben, die zum Sweet Spot einer vereinfachten asynchronen Netzwerkbibliothek passt!
[edit: Vielen Dank an intgr für seinen Zeiger auf diese Seite . Wenn Sie nach unten scrollen, werden Sie sehen, dass es eine wirklich schöne Liste von Projekten gibt, die darauf abzielen, diese Aufgabe auf die eine oder andere Weise anzugehen. Es scheint tatsächlich, dass sich die Dinge seit der Einführung von Twisted tatsächlich weiterentwickelt haben: Die Menschen scheinen nun eine auf Co-Routine basierende Lösung gegenüber einer herkömmlichen reaktor- / rückruforientierten Lösung zu bevorzugen . Die Vorteile dieses Ansatzes sind klarer, direkterer Code: Ich habe ihn sicherlich in der Vergangenheit gefunden, insbesondere bei der Arbeit mit boost.asioIn C ++ kann dieser auf Rückrufen basierende Code zu Designs führen, die schwer zu verfolgen sind und für das ungeübte Auge relativ dunkel sind. Durch die Verwendung von Co-Routinen können Sie Code schreiben, der zumindest etwas synchroner aussieht. Ich denke, jetzt ist es meine Aufgabe, herauszufinden, welche dieser vielen Bibliotheken mir gefällt, und es auszuprobieren! Ich bin froh, dass ich jetzt gefragt habe ...]
[Bearbeiten: Vielleicht von Interesse für jeden, der diese Frage verfolgt oder über sie gestolpert ist oder sich in irgendeiner Weise um dieses Thema kümmert: Ich habe eine wirklich gute Zusammenfassung des aktuellen Status der verfügbaren Tools für diesen Job gefunden]
select
für das E / A-Multiplexing verwendet wird. Aber Sie sollten in der Lage sein, mit Tornado-Pyuv eine anständige Leistung zu erzielen . 2. In Python 3.3+ und seinem Backport- Trollius gibt es jetzt Asyncio , mit dem jede Tornado-Anwendung in ihrer Ereignisschleife ausgeführt werden kann (Twisted wird bald unterstützt).Antworten:
Ich mochte das Concurrence- Python-Modul, das entweder Stackless Python-Mikrothreads oder Greenlets für leichtes Threading verwendet. Alle blockierenden Netzwerk-E / A werden transparent über eine einzige
libevent
Schleife asynchronisiert , sodass sie fast so effizient sein sollten wie ein echter asynchroner Server.Ich nehme an, es ist Eventlet auf diese Weise ähnlich.
Der Nachteil ist, dass sich die API stark von Pythons
sockets
/threading
Modulen unterscheidet. Sie müssen ein gutes Stück Ihrer Anwendung neu schreiben (oder eine Kompatibilitäts-Shim-Ebene schreiben).Bearbeiten: Es scheint, dass es auch Cogen gibt , das ähnlich ist, aber anstelle von Greenlets die erweiterten Generatoren von Python 2.5 für seine Coroutinen verwendet. Dies macht es portabler als Concurrence und andere Alternativen. Netzwerk-E / A erfolgt direkt mit epoll / kqueue / iocp.
quelle
Twisted ist komplex, da haben Sie Recht. Verdreht ist nicht aufgebläht.
Wenn Sie hier einen Blick darauf werfen: http://twistedmatrix.com/trac/browser/trunk/twisted finden Sie eine organisierte, umfassende und sehr gut getestete Suite mit vielen Protokollen des Internets sowie Hilfecode zum Schreiben und sehr ausgefeilte Netzwerkanwendungen bereitstellen. Ich würde Aufblähen nicht mit Vollständigkeit verwechseln.
Es ist bekannt, dass die Twisted-Dokumentation auf den ersten Blick nicht besonders benutzerfreundlich ist, und ich glaube, dass dies eine unglückliche Anzahl von Menschen abweist. Aber Twisted ist erstaunlich (IMHO), wenn Sie die Zeit investieren. Ich habe es getan und es hat sich gelohnt, und ich würde anderen empfehlen, dasselbe zu versuchen.
quelle
gevent ist eventlet aufgeräumt .
API-weise folgt es den gleichen Konventionen wie die Standardbibliothek (insbesondere Threading- und Multiprocessing-Module), wo es sinnvoll ist. Sie haben also vertraute Dinge wie Warteschlange und Ereignis , mit denen Sie arbeiten können.
Es unterstützt nur libevent ( Update: libev seit 1.0 ) als Reaktorimplementierung, nutzt es jedoch voll aus. Es verfügt über einen schnellen WSGI-Server, der auf libevent-http basiert und DNS-Abfragen über libevent-dns löst, anstatt wie die meisten anderen Bibliotheken einen Thread-Pool zu verwenden machen. ( Update: Da 1.0 c-ares verwendet wird, um asynchrone DNS-Abfragen durchzuführen, ist Threadpool ebenfalls eine Option.)
Wie bei einem Eventlet werden die Rückrufe und Zurückstellungen durch die Verwendung von Greenlets unnötig .
Schauen Sie sich die Beispiele an: gleichzeitiges Herunterladen mehrerer URLs , langes Abrufen von Webchat .
quelle
Einen wirklich interessanten Vergleich solcher Frameworks hat Nicholas Piël in seinem Blog zusammengestellt: Es ist eine Lektüre wert!
quelle
Keine dieser Lösungen wird die Tatsache vermeiden, dass die GIL die CPU-Parallelität verhindert - sie sind nur bessere Möglichkeiten, um E / A-Parallelität zu erhalten, die Sie bereits mit Threads haben. Wenn Sie der Meinung sind, dass Sie eine bessere E / A-Leistung erzielen können, verfolgen Sie auf jeden Fall eine dieser Möglichkeiten. Wenn Ihr Engpass jedoch bei der Verarbeitung der Ergebnisse liegt, hilft hier nichts außer dem Multiprozessor-Modul.
quelle
Ich würde nicht so weit gehen, Twisted als aufgebläht zu bezeichnen, aber es ist schwierig, den Kopf herumzureißen. Ich habe es eine ganze Weile vermieden, mich wirklich auf ein Lernen einzulassen, da ich immer etwas Leichteres für 'kleine Aufgaben' wollte.
Jetzt, da ich noch mehr damit gearbeitet habe, muss ich sagen, dass es SEHR schön ist, alle Batterien im Lieferumfang zu haben.
Alle anderen asynchronen Bibliotheken, mit denen ich gearbeitet habe, sind viel weniger ausgereift, als sie überhaupt erscheinen. Die Ereignisschleife von Twisted ist solide.
Ich bin mir nicht ganz sicher, wie ich die steile Twisted-Lernkurve lösen soll. Es könnte hilfreich sein, wenn jemand es gabelt und ein paar Dinge aufräumt, wie das Entfernen aller Abwärtskompatibilitäts-Cruft und der toten Projekte. Aber das ist die Natur ausgereifter Software, denke ich.
quelle
PortableGtkReactor
?Kamaelia wurde noch nicht erwähnt. Das Parallelitätsmodell basiert auf der Verkabelung von Komponenten mit Nachrichten, die zwischen Posteingängen und Postausgängen übertragen werden. Hier ist eine kurze Übersicht.
quelle
Ich habe angefangen, Twisted für einige Dinge zu verwenden. Das Schöne daran ist fast, dass es "aufgebläht" ist. Es gibt Anschlüsse für nahezu jedes der Hauptprotokolle. Sie können einen Jabber-Bot haben, der Befehle entgegennimmt und auf einem IRC-Server veröffentlicht, per E-Mail an jemanden sendet, einen Befehl ausführt, von einem NNTP-Server liest und eine Webseite auf Änderungen überwacht. Die schlechte Nachricht ist, dass es all das kann und die Dinge für einfache Aufgaben wie das erklärte OP übermäßig komplex machen kann. Der Vorteil von Python ist jedoch, dass Sie nur das angeben, was Sie benötigen. Während der Download 20 MB groß sein kann, können Sie nur 2 MB Bibliotheken einschließen (was immer noch viel ist). Meine größte Beschwerde bei Twisted ist, obwohl sie Beispiele enthalten, alles, was über einen einfachen TCP-Server hinausgeht, den Sie selbst sind.
Obwohl es sich nicht um eine Python-Lösung handelt, habe node.js in letzter Zeit viel mehr Zugkraft erlangt. Tatsächlich habe ich darüber nachgedacht, nach kleineren Projekten zu suchen, aber ich erschrecke nur, wenn ich Javascript höre :)
quelle
Es gibt ein gutes Buch zu diesem Thema: "Twisted Network Programming Essentials" von Abe Fettig. Die Beispiele zeigen, wie man sehr pythonischen Code schreibt, und für mich persönlich scheint mir das nicht auf einem aufgeblähten Framework zu beruhen. Schauen Sie sich die Lösungen im Buch an. Wenn sie nicht sauber sind, weiß ich nicht, was sauber bedeutet.
Mein einziges Rätsel ist das gleiche, das ich mit anderen Frameworks wie Ruby habe. Ich mache mir Sorgen, vergrößert es sich? Ich würde es hassen, einen Client für ein Framework zu verpflichten, das Skalierbarkeitsprobleme haben wird.
quelle
Whizzer ist ein winziges asynchrones Socket-Framework, das Pyev verwendet. Es ist sehr schnell, vor allem wegen Pyev. Es wird versucht, eine ähnliche Schnittstelle bereitzustellen, die mit einigen geringfügigen Änderungen verdreht ist.
quelle
Versuchen Sie auch Syncless . Es basiert auf Coroutine (ähnelt also Concurrence, Eventlet und Gevent). Es implementiert nicht blockierende Drop-In-Ersetzungen für socket.socket, socket.gethostbyname (usw.), ssl.SSLSocket, time.sleep und select.select. Es ist schnell. Es braucht Stackless Python und Libevent. Es enthält eine obligatorische Python-Erweiterung, die in C (Pyrex / Cython) geschrieben ist.
quelle
Ich bestätige die Güte der Synchronität . Es kann libev (die neuere, sauberere und leistungsfähigere Version von libevent) verwenden. Vor einiger Zeit hat es nicht so viel Unterstützung wie libevent, aber jetzt geht der Entwicklungsprozess weiter und ist sehr nützlich.
quelle
Wenn Sie nur eine vereinfachte, leichte HTTP-Anforderungsbibliothek möchten, finde ich Unirest wirklich gut
quelle
Sie können sich gerne PyWorks ansehen, das einen ganz anderen Ansatz verfolgt. Es lässt Objektinstanzen in ihrem eigenen Thread ausgeführt werden und führt Funktionsaufrufe für dieses Objekt asynchron aus.
Lassen Sie einfach eine Klasse von Task anstelle von Objekt erben und es ist asynchron. Alle Methodenaufrufe sind Proxies. Rückgabewerte (falls erforderlich) sind zukünftige Proxys.
PyWorks finden Sie unter http://bitbucket.org/raindog/pyworks
quelle