在 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)
来源: https://blog.csdn.net/voidcc/article/details/25482551