PyPI-Pakete
Ab Juni 2020 sind dies die ereignisbezogenen Pakete, die auf PyPI verfügbar sind und nach dem letzten Veröffentlichungsdatum sortiert sind.
Es gibt mehr
Das sind viele Bibliotheken zur Auswahl, die eine sehr unterschiedliche Terminologie verwenden (Ereignisse, Signale, Handler, Methodenversand, Hooks, ...).
Ich versuche, einen Überblick über die oben genannten Pakete sowie die in den Antworten hier genannten Techniken zu behalten.
Zunächst einige Begriffe ...
Beobachtermuster
Der grundlegendste Stil des Ereignissystems ist die 'Bag of Handler-Methode', die eine einfache Implementierung des Observer-Musters darstellt .
Grundsätzlich werden die Handler-Methoden (Callables) in einem Array gespeichert und jeweils aufgerufen, wenn das Ereignis 'ausgelöst' wird.
Veröffentlichen-Abonnieren
Der Nachteil von Observer-Ereignissystemen besteht darin, dass Sie die Handler nur für das tatsächliche Ereignisobjekt (oder die Handlerliste) registrieren können. Zum Zeitpunkt der Registrierung muss die Veranstaltung also bereits vorhanden sein.
Aus diesem Grund gibt es den zweiten Stil von Ereignissystemen: das
Publish-Subscribe-Muster . Hier registrieren sich die Handler nicht für ein Ereignisobjekt (oder eine Handlerliste), sondern für einen zentralen Dispatcher. Auch die Benachrichtiger sprechen nur mit dem Dispatcher. Was zu hören oder zu veröffentlichen ist, wird durch 'Signal' bestimmt, das nichts weiter als ein Name (Zeichenfolge) ist.
Vermittlermuster
Könnte auch von Interesse sein: das Mediator-Muster .
Haken
Ein 'Hook'-System wird üblicherweise im Zusammenhang mit Anwendungs-Plugins verwendet. Die Anwendung enthält feste Integrationspunkte (Hooks), und jedes Plugin kann eine Verbindung zu diesem Hook herstellen und bestimmte Aktionen ausführen.
Andere Ereignisse'
Hinweis: threading.Event ist kein 'Ereignissystem' im obigen Sinne. Es ist ein Thread-Synchronisationssystem, bei dem ein Thread wartet, bis ein anderer Thread das Ereignisobjekt "signalisiert".
Netzwerk-Messaging-Bibliotheken verwenden häufig auch den Begriff "Ereignisse". manchmal sind diese im Konzept ähnlich; manchmal nicht. Sie können natürlich Thread-, Prozess- und Computergrenzen überschreiten. Siehe zB
pyzmq , pymq ,
Twisted , Tornado , gevent , eventlet .
Schwache Referenzen
Wenn Sie in Python einen Verweis auf eine Methode oder ein Objekt halten, wird sichergestellt, dass dieser nicht vom Garbage Collector gelöscht wird. Dies kann wünschenswert sein, kann aber auch zu Speicherverlusten führen: Die verknüpften Handler werden niemals bereinigt.
Einige Ereignissysteme verwenden schwache Referenzen anstelle regulärer Referenzen, um dies zu lösen.
Einige Worte zu den verschiedenen Bibliotheken
Ereignissysteme im Beobachterstil:
- zope.event zeigt, wie das funktioniert (siehe Lennarts Antwort ). Hinweis: Dieses Beispiel unterstützt nicht einmal Handlerargumente.
- Die 'Callable List'- Implementierung von LongPoke zeigt, dass ein solches Ereignissystem durch Unterklassen sehr minimalistisch implementiert werden kann
list
.
- Felks Variation EventHook sorgt auch für die Signaturen von Anrufern und Anrufern.
- spassigs EventHook (Michael Foords Event Pattern) ist eine einfache Implementierung.
- Die Ereignisklasse "Wertvolle Lektionen" von Josip ist im Grunde dieselbe, verwendet jedoch a
set
anstelle von a list
, um die Tasche zu speichern, und implementiert Geräte, __call__
die beide sinnvolle Ergänzungen sind.
- PyNotify hat ein ähnliches Konzept und bietet zusätzliche Konzepte für Variablen und Bedingungen ('variabel geändertes Ereignis'). Die Homepage funktioniert nicht.
- axel ist im Grunde ein Bag-of-Handler mit mehr Funktionen in Bezug auf Threading, Fehlerbehandlung, ...
- Für Python-Dispatch müssen die geraden Quellklassen abgeleitet werden
pydispatch.Dispatcher
.
- buslane ist klassenbasiert, unterstützt Einzel- oder Mehrfachhandler und ermöglicht umfangreiche Typhinweise.
- Pithikos ' Observer / Event ist ein leichtes Design.
Publish-Subscribe-Bibliotheken:
- Blinker hat einige raffinierte Funktionen wie automatische Trennung und Filterung basierend auf dem Absender.
- PyPubSub ist ein stabiles Paket und verspricht "erweiterte Funktionen, die das Debuggen und Verwalten von Themen und Nachrichten erleichtern".
- pymitter ist ein Python-Port von Node.js EventEmitter2 und bietet Namespaces, Platzhalter und TTL.
- PyDispatcher scheint die Flexibilität in Bezug auf viele-zu-viele-Veröffentlichungen usw. zu betonen. Unterstützt schwache Referenzen.
- louie ist ein überarbeiteter PyDispatcher und sollte "in einer Vielzahl von Kontexten" arbeiten.
- pypydispatcher basiert auf (Sie haben es erraten ...) PyDispatcher und funktioniert auch in PyPy.
- django.dispatch ist ein umgeschriebener PyDispatcher "mit einer eingeschränkteren Oberfläche, aber höherer Leistung".
- pyeventdispatcher basiert auf dem Event-Dispatcher des Symfony-Frameworks von PHP.
- Der Dispatcher wurde aus django.dispatch extrahiert, wird aber ziemlich alt.
- Cristian Garcias EventManger ist eine sehr kurze Implementierung.
Andere:
- pluggy enthält ein Hook-System, das von
pytest
Plugins verwendet wird .
- RxPy3 implementiert das Observable-Muster und ermöglicht das Zusammenführen von Ereignissen, erneuten Versuchen usw.
- Die Signale und Slots von Qt sind bei PyQt
oder PySide2 erhältlich . Sie funktionieren als Rückruf, wenn sie im selben Thread verwendet werden, oder als Ereignisse (mithilfe einer Ereignisschleife) zwischen zwei verschiedenen Threads. Signale und Slots haben die Einschränkung, dass sie nur in Objekten von Klassen funktionieren, von denen abgeleitet ist
QObject
.