哪些 Python 包提供独立的事件系统?

2022-01-15 00:00:00 python events event-handling dispatcher

问题描述

我知道 pydispatcher,但必须有其他与 Python 相关的事件包.

I am aware of pydispatcher, but there must be other event-related packages around for Python.

哪些库可用?

我对大型框架中的事件管理器不感兴趣,我宁愿使用可以轻松扩展的小型准系统解决方案.

I'm not interested in event managers that are part of large frameworks, I'd rather use a small bare-bones solution that I can easily extend.


解决方案

PyPI 包

截至 2021 年 1 月,这些是 PyPI 上可用的与事件相关的软件包,按最近的发布日期排序.

PyPI packages

As of January 2021, these are the event-related packages available on PyPI, ordered by most recent release date.

  • pymitter 0.3.0:2020 年 11 月
  • zope.event 4.5.0:2020 年 9 月
  • python-dispatch 0.1.31:2020 年 8 月
  • RxPy3 1.0.1:2020 年 6 月
  • pluggy 0.13.1:2020 年 6 月(测试版)李>
  • Louie 2.0:2019 年 9 月
  • PyPubSub 4.0.3:2019 年 1 月
  • pyeventdispatcher 0.2.3a0:2018
  • buslane 0.0.5: 2018
  • PyPyDispatcher 2.1.2:2017
  • axel 0.0.7: 2016
  • blinker 1.4:2015
  • PyDispatcher 2.0.5:2015
  • dispatcher 1.0:2012
  • py-notify 0.3.1:2008李>
  • pymitter 0.3.0: Nov 2020
  • zope.event 4.5.0: Sept 2020
  • python-dispatch 0.1.31: Aug 2020
  • RxPy3 1.0.1: June 2020
  • pluggy 0.13.1: June 2020 (beta)
  • Louie 2.0: Sept 2019
  • PyPubSub 4.0.3: Jan 2019
  • pyeventdispatcher 0.2.3a0: 2018
  • buslane 0.0.5: 2018
  • PyPyDispatcher 2.1.2: 2017
  • axel 0.0.7: 2016
  • blinker 1.4: 2015
  • PyDispatcher 2.0.5: 2015
  • dispatcher 1.0: 2012
  • py-notify 0.3.1: 2008

有很多库可供选择,使用非常不同的术语(事件、信号、处理程序、方法分派、钩子......).

That's a lot of libraries to choose from, using very different terminology (events, signals, handlers, method dispatch, hooks, ...).

我试图保持对上述软件包的概述,以及此处答案中提到的技术.

I'm trying to keep an overview of the above packages, plus the techniques mentioned in the answers here.

首先,一些术语......

First, some terminology...

事件系统最基本的风格是处理方法包",它是一个观察者模式的简单实现.

The most basic style of event system is the 'bag of handler methods', which is a simple implementation of the Observer pattern.

基本上,处理程序方法(可调用对象)存储在一个数组中,并在事件触发"时调用.

Basically, the handler methods (callables) are stored in an array and are each called when the event 'fires'.

观察者事件系统的缺点是你只能在实际事件上注册处理程序对象(或处理程序列表).因此,在注册时,该事件已经存在.

The disadvantage of Observer event systems is that you can only register the handlers on the actual Event object (or handlers list). So at registration time the event already needs to exist.

这就是存在第二种事件系统的原因:发布-订阅模式.在这里,处理程序不是在事件对象(或处理程序列表)上注册,而是在中央调度程序上注册.此外,通知者只与调度员交谈.听什么或发布什么是由信号"决定,它只不过是一个名称(字符串).

That's why the second style of event systems exists: the publish-subscribe pattern. Here, the handlers don't register on an event object (or handler list), but on a central dispatcher. Also the notifiers only talk to the dispatcher. What to listen for, or what to publish is determined by 'signal', which is nothing more than a name (string).

也可能感兴趣:中介者模式.

挂钩"系统通常用于应用程序插件的上下文中.这应用程序包含固定的集成点(钩子),每个插件可能连接到该钩子并执行某些操作.

A 'hook' system is usally used in the context of application plugins. The application contains fixed integration points (hooks), and each plugin may connect to that hook and perform certain actions.

注意:threading.Event 不是事件"系统'在上述意义上.这是一个线程同步系统,其中一个线程一直等待,直到另一个线程发出信号"事件对象.

Note: threading.Event is not an 'event system' in the above sense. It's a thread synchronization system where one thread waits until another thread 'signals' the Event object.

网络消息传递库也经常使用事件"一词;有时这些在概念上是相似的;有时不是.它们当然可以跨越线程、进程和计算机边界.参见例如pyzmq, pymq,扭曲, 龙卷风, gevent, 小事件.

Network messaging libraries often use the term 'events' too; sometimes these are similar in concept; sometimes not. They can of course traverse thread-, process- and computer boundaries. See e.g. pyzmq, pymq, Twisted, Tornado, gevent, eventlet.

在 Python 中,持有对方法或对象的引用可确保它不会被删除由垃圾收集器.这可能是可取的,但也可能导致内存泄漏:链接的处理程序永远不会清理干净.

In Python, holding a reference to a method or object ensures that it won't get deleted by the garbage collector. This can be desirable, but it can also lead to memory leaks: the linked handlers are never cleaned up.

一些事件系统使用弱引用而不是常规引用来解决这个问题.

Some event systems use weak references instead of regular ones to solve this.

观察者式事件系统:

  • zope.event 展示了它的工作原理(参见 Lennart 的回答).注意:此示例甚至不支持处理程序参数.
  • LongPoke 的 'callable list' 实现表明,通过继承 list 可以非常简约地实现这样的事件系统.
  • Felk 的变体 EventHook 还确保了被调用者和调用者的签名.
  • spassig 的 EventHook(Michael Foord 的事件模式)是一个简单的实现.
  • Josip 的 Valued Lessons Event 类 基本相同,只是使用了 set 而不是一个 list 来存储包,并实现 __call__ 这两个都是合理的添加.
  • PyNotify 在概念上类似,也提供了额外的变量和条件概念('variable改变事件').主页无法正常工作.
  • axel 基本上是一个处理程序包,具有更多与线程、错误处理相关的功能, ...
  • python-dispatch 要求偶数源类派生自 pydispatch.Dispatcher.
  • buslane 是基于类的,支持单个或多个处理程序并促进广泛的类型提示.
  • Pithikos 的 Observer/Event 是一种轻量级设计.
  • zope.event shows the bare bones of how this works (see Lennart's answer). Note: this example does not even support handler arguments.
  • LongPoke's 'callable list' implementation shows that such an event system can be implemented very minimalistically by subclassing list.
  • Felk's variation EventHook also ensures the signatures of callees and callers.
  • spassig's EventHook (Michael Foord's Event Pattern) is a straightforward implementation.
  • Josip's Valued Lessons Event class is basically the same, but uses a set instead of a list to store the bag, and implements __call__ which are both reasonable additions.
  • PyNotify is similar in concept and also provides additional concepts of variables and conditions ('variable changed event'). Homepage is not functional.
  • axel is basically a bag-of-handlers with more features related to threading, error handling, ...
  • python-dispatch requires the even source classes to derive from pydispatch.Dispatcher.
  • buslane is class-based, supports single- or multiple handlers and facilitates extensive type hints.
  • Pithikos' Observer/Event is a lightweight design.

发布-订阅库:

  • blinker 具有一些漂亮的功能,例如自动断开连接和基于发件人的过滤.
  • PyPubSub 是一个稳定的包,并承诺有助于调试和维护的高级功能主题和消息".
  • pymitter 是 Node.js EventEmitter2 的 Python 端口,提供命名空间、通配符和 TTL.李>
  • PyDispatcher 似乎强调多对多发布等方面的灵活性.支持弱引用.
  • louie 是一个重新设计的 PyDispatcher,应该可以在各种环境中"工作.李>
  • pypydispatcher 基于(你猜对了……)PyDispatcher 并且也适用于 PyPy.
  • django.dispatch 是一个重写的 PyDispatcher,具有更多接口有限,但性能更高".
  • pyeventdispatcher 基于 PHP 的 Symfony 框架的事件调度器.
  • dispatcher 是从 django.dispatch 中提取出来的,但是已经相当老了.
  • Cristian Garcia 的 EventManger 是一个非常简短的实现.
  • blinker has some nifty features such as automatic disconnection and filtering based on sender.
  • PyPubSub is a stable package, and promises "advanced features that facilitate debugging and maintaining topics and messages".
  • pymitter is a Python port of Node.js EventEmitter2 and offers namespaces, wildcards and TTL.
  • PyDispatcher seems to emphasize flexibility with regards to many-to-many publication etc. Supports weak references.
  • louie is a reworked PyDispatcher and should work "in a wide variety of contexts".
  • pypydispatcher is based on (you guessed it...) PyDispatcher and also works in PyPy.
  • django.dispatch is a rewritten PyDispatcher "with a more limited interface, but higher performance".
  • pyeventdispatcher is based on PHP's Symfony framework's event-dispatcher.
  • dispatcher was extracted from django.dispatch but is getting fairly old.
  • Cristian Garcia's EventManger is a really short implementation.

其他:

  • pluggy 包含一个供 pytest 插件使用的钩子系统.
  • RxPy3 实现了 Observable 模式并允许合并事件、重试等.
  • Qt 的信号和插槽可从 PyQt 获得或 PySide2.当在同一个线程中使用时,它们作为回调工作,或作为两个不同线程之间的事件(使用事件循环).Signals 和 Slots 的局限性在于它们仅适用于从 QObject 派生的类的对象.
  • pluggy contains a hook system which is used by pytest plugins.
  • RxPy3 implements the Observable pattern and allows merging events, retry etc.
  • Qt's Signals and Slots are available from PyQt or PySide2. They work as callback when used in the same thread, or as events (using an event loop) between two different threads. Signals and Slots have the limitation that they only work in objects of classes that derive from QObject.

相关文章