原创博文,转载请说明出处:点击打开链接
在POX的事件系统中,事件处理需要有发布(publish)者和订阅(subscribe)者,二者缺一不可。
POX中定义的事件都是revent.Event类的子类,还有一种用来发布事件的类都是revent.EventMixin类的子类,这个类也通常是组件中用来向core中注册的类。
因此,在写自己的组件的时候,需要在头部加上
from pox.lib.revent.revent import EventMixin
from pox.lib.revent.revent import Event
或者干脆直接写
from pox.lib.revent import *
或者
from pox.lib.revent.revent import *
在发布事件的类中,通常还有一个名为_eventMixin_Events的变量(集合)来列出其可能抛出的事件,通常出现在这个类定义开始的位置。
借用POX wiki上的例子来具体分析:
class Chef (EventMixin):
"""
Class modeling a world class chef
This chef only knows how to prepare spam, but we assume does it really well.
"""
_eventMixin_events = set([
SpamStarted,
SpamFinished,
])
在Chef类中,可以抛出两个事件,分别是SpamStarted和SpamFinished。
wiki中同时也给出了事件SpamStarted的定义:class SpamStarted (Event):
def __init__ (self, brand = "Hormel"):
Event.__init__(self)
self.brand = brand
@property
def genuine (self):
# If it's not Hormel, it's just canned spiced ham!
return self.brand == "Hormel"
抛出事件的时候,在类Chef中可以使用以下代码(当然是在类里面的方法中):
self.raiseEvent(SpamStarted, brand)
没错,brand就是SpamStarted中__init__的参数,用来向监听者传递有用的信息。当然也可以不加这个参数,这样会使用默认参数(如果在事件中有定义的话)。
那Chef抛出的事件会有谁来处理呢?因此需要添加事件的handler。
如果我们定义了一个函数用来处理SpamFinished事件:
def spam_ready (event):
print "Spam is ready! Smells delicious!"
那么我们可以使用以下代码来使spam_ready函数成为SpamFinished事件的监听者。
chef.addListener(SpamFinished, spam_ready)
其中chef是类Chef类的一个实例化对象。
在通常情况下,用来监听事件的函数都是在一个类中,这个类同时可以监听多个事件。
class HungryPerson (object):
""" Models a person that loves to eat spam """
def __init__ (self):
chef.addListeners(self)
def _handle_SpamStarted (self, event):
print "I can't wait to eat!"
def _handle_SpamFinished (self, event):
print "Spam is ready! Smells delicious!"
在这个类中,__init__方法的功能是对这个类添加对chef的监听,那么chef抛出的事件都可以被HungryPerson来监听和处理,在对应的事件前面加上_handle_来命名方法就可以处理对应的事件了。
如果Chef这个类被注册到core中话,我们还可以在__init__中通过以下方法添加监听:
self.listenTo(core.Chef)