PyPI软件包
截至2020年6月,这些都是PyPI上与事件相关的软件包,按最新发布日期订购。
- RxPy3
1.0.1
:2020年6月 - 拙劣的
0.13.1
:2020年6月 - 路易
2.0
:2019年9月 - python-dispatch
0.1.2
:2019年2月 - PyPubSub
4.0.3
:2019年1月 - zope.event
4.4
:2018年 - pyeventdispatcher
0.2.3a0
:2018年 - 布兰妮
0.0.5
:2018 - PyPyDispatcher
2.1.2
:2017年 - 轴心
0.0.7
:2016 - 信号灯
1.4
:2015 - PyDispatcher
2.0.5
:2015年 - 痛点
0.2.3
:2014 - 调度员
1.0
:2012 - py-notify
0.3.1
:2008
还有更多
使用非常不同的术语(事件,信号,处理程序,方法分派,hook等),可以选择很多库。
我试图对上述软件包以及此处答案中提到的技术进行概述。
首先,一些术语…
观察者模式
事件系统最基本的样式是“处理程序方法包”,这是Observer模式的简单实现。
基本上,处理程序方法(可调用对象)存储在数组中,并在事件“触发”时分别调用。
发布-订阅
Observer事件系统的缺点是只能在实际的Event对象(或处理程序列表)上注册处理程序。因此,在注册时,该事件已经需要存在。
这就是为什么存在事件系统的第二种样式的原因: publish-subscribe
pattern。在这里,处理程序不在事件对象(或处理程序列表)上注册,而是在中央调度程序上注册。通知者也仅与调度程序对话。听什么或发布什么由“信号”决定,它仅是名称(字符串)。
中介者模式
可能也很有趣:中介者模式。
钩子
在应用程序插件的上下文中通常使用“挂钩”系统。该应用程序包含固定的集成点(挂钩),并且每个插件都可以连接到该挂钩并执行某些操作。
其他“事件”
注意:从上述意义上讲,threading.Event不是“事件系统”。这是一个线程同步系统,其中一个线程等待,直到另一个线程“标记” Event对象。
网络消息传递库也经常使用术语“事件”。有时这些在概念上是相似的;有时不是。它们当然可以遍历线程,进程和计算机的边界。参见例如
pyzmq,pymq,
Twisted,Tornado,
gevent,eventlet。
参考不足
在Python中,持有对方法或对象的引用可确保不会被垃圾收集器删除。这可能是理想的,但也可能导致内存泄漏:永远不会清除链接的处理程序。
一些事件系统使用弱引用而不是常规引用来解决此问题。
关于各种库的一些话
观察者风格的事件系统:
- zope.event显示了其工作原理的基本内容(请参阅Lennart的答案)。注意:此示例甚至不支持处理程序参数。
- LongPoke的“可调用列表”实现表明,可以通过子类化非常简单地实现这样的事件系统
list
。 - Felk的变体EventHook还可以确保被呼叫者和呼叫者的签名。
- spassig的EventHook(Michael Foord的事件模式)是一个简单的实现。
- Josip的Valued LessonsEvent类基本上是相同的,但是使用a
set
代替alist
来存储包,并且实现__call__
都是合理的补充。 - PyNotify在概念上类似,还提供了变量和条件(“变量更改事件”)的其他概念。主页不起作用。
- axel基本上是一个处理程序包,具有更多与线程,错误处理,…相关的功能。
- python-dispatch需要偶数源类从派生
pydispatch.Dispatcher
。 - buslane是基于类的,支持单个或多个处理程序,并有助于扩展类型提示。
- Pithikos的Observer / Event是轻巧的设计。



