Package: scouter
# scouter定义一群类似 Python 内置数据结构的一群数据结构，数据结构发生变化的时候，发生回调。同时 scouter 还包含了一个易于配置的装饰器模式的 FSM，可以支持 SOP 与 OOP 的结合。## 安装方法：```bashpip install scouter```或者 `easy_install`或者下载源代码:```bashcd scouterpython setup.py install```## 使用方法：### SVar 使用回调函数监视变量```pythonfrom scouter import SVardef callback(now, orig):print 'Orig:{} Now:{}'.format(orig, now)var = SVar(4, callback)var.value = 5```对于一个 SVar 对象，在定义的时候，可以添加一个回调函数，这个回调函数只接受两个参数：* 第一个参数为当前新的值* 第二个参数为原来的值### SList 使用回调函数监视列表结构```pythonfrom scouter import SListdef print_cb(obj, index):print obj, indexdef print_new(_new, orig):print 'new:{} orig:{}'.format(_new, orig)_list = SList(value=['aaaaaaaa',2,3,4,5],add_new_item_callback=print_cb,del_new_item_callback=print_cb,new_list_value_callback=print_new)_list.append('asdf')_list.pop(0)for i in _list:print iassert 4 == _list[2]del _list[2]_list.value = [1,2,3,4,5,]```对于一个 SList 对象，在定义的时候，可以添加三个回调函数，这三个回调函数的参数都有两个参数：* 对于 add_new_item_callback 来说，第一个参数是添加的新值，第二个参数是索引* 对于 del_new_item_callback 来说，第一个参数是被删除的值，第二个参数是索引* 对于 new_list_value_callback 来说，第一个参数是现在的新值，第二个参数是之前的 value```pythonfrom scouter import SDictdef print_kv(key, value):print 'key:{} value:{}'.format(key, value)def print_new(new, orig):print 'new:{}, orig:{}'.format(new, orig)_dict = SDict({1:2,'key':'value'},new_kv_callback=print_kv,del_kv_callback=print_kv,new_value_callback=print_new)_dict['key'] = 'hhhhhhhhhvalue1'_dict['key1'] = 'hhhhhhhhhvalue12'del _dict[1]_dict.value = {5:4}```基本同上，只是对于 new_kv_callback/del_kv_callback 来说两个参数分别为 key 和 value。### SOP FSM更加容易定义更加容易使用的 FSM。```python下面是测试用例中的例子def test_fsm(self):""""""state_START = 'start'state_RUNNING = 'running'state_END = 'end'class FSMDemo(FSMBase):_fsm = FSM()#----------------------------------------------------------------------def config(self):""""""self._fsm.preset_all_states(state_END, state_RUNNING, state_START)self._fsm.set_start(state_START)self._fsm.set_end(state_END)@_fsm.transfer(orig=state_START, dest=state_RUNNING)def action_run(self):""""""print('Run!')@_fsm.onstate(state_RUNNING, state_START)def say_tired(self):""""""print('I am tired')self.action_stop()@_fsm.transfer(orig=state_RUNNING, dest=state_END)def action_stop(self):""""""print('Stop working!')s = FSMDemo()print(s.state)assert s.state == state_STARTs.action_run()assert s.state == state_RUNNINGs.say_tired()self.assertRaises(FSMError, callableObj=s.say_tired)```关键点在定义一个类变量为 FSM 对象，然后在 config 中配置这个 FSM 对象的预设状态和起始状态，然后定义回调函数通过修饰调用，如果需要限制某一个方法只能在某个特殊状态下使用，需要使用 onstate 这个特殊修饰器修饰。当然，onstate 的参数为你想执行你的这个放在所在的状态：比如你想让你的方法执行在 run/waiting/watching 中，你就需要 `@_fsm.onstate(run, waiting, watching)` 。当你执行 `@_fsm.transfer` 修饰过的方法的时候，状态转换被直接执行当然，FSM 和 FSMBase 都有一个 state 属性来标记当前的状态。#### 另一种 FSM 的用法（action 驱动）使用动作驱动的 FSM 也是非常有必要的。修饰器使用 FSM 适合实例作为一个单例。```pythonstate_START = 'start'state_END = 'end'state_INITINT = 'initing'state_WORKING = 'working'_all_states = [state_END,state_INITINT,state_START,state_WORKING]s = FSM(state_START, state_END, _all_states)## 注册行为#s.create_action(action_name='initing', orig=state_START,dest=state_INITINT)print('-'*50)print s.state## 确认初始状态#self.assertTrue(s.state == state_START)## 调用行为导致 状态变化#s.action('initing')assert s.state == state_INITINTprint('-'*50)```