基於python的事件處理模型

fisher虞發表於2018-03-28

1.事件、事件源,事件序號產生器與分發器

# -*- coding: utf-8 -*-


from enum import Enum
from collections import defaultdict


class Event(object):
    def __init__(self, event_type, **kwargs):
        self.__dict__ = kwargs
        self.event_type = event_type

    def __repr__(self):
        return ' '.join('{}:{}'.format(k, v) for k, v in self.__dict__.items())

class EventBus(object):
    def __init__(self):
        self._listeners = defaultdict(list)
        self._listeners[EVENT.PRE_EAT].append(self._pre_eat)
        self._listeners[EVENT.POST_EAT].append(self._post_eat)
        self._listeners[EVENT.PRE_SLEEP].append(self._pre_sleep)

    def add_listener(self, event, listener):
        self._listeners[event].append(listener)

    def prepend_listener(self, event, listener):
        self._listeners[event].insert(0, listener)

    def publish_event(self, event):
        for l in self._listeners[event.event_type]:
            # # 如果返回 True ,那麼訊息不再傳遞下去
            if l(event):
                break

    def _pre_eat(self,event):
        print('吃飯前先洗手')

    def _post_eat(self,event):
        print('吃飯後洗碗')

    def _pre_sleep(self,event):
        print('睡覺請關燈')


class EventSource(object):

    def __init__(self):
        self.events = []

    def add(self,event):
        self.events.append(event)


class EVENT(Enum):
    # 吃飯
    EAT = 'eat'
    #睡覺
    SLEEP = 'sleep'
    # 吃飯前觸發
    PRE_EAT = 'pre_eat'
    #吃飯後觸發
    POST_EAT = 'post_eat'
    # 睡覺前觸發
    PRE_SLEEP = 'pre_sleep'

def parse_event(event_str):
    return EVENT.__members__.get(event_str.upper(), None)

2.存放事件源和事件序號產生器以及分發器的環境

# -*- coding: utf-8 -*-


from event import EventBus,EventSource

class Environment(object):
    _env = None

    def __init__(self):
        Environment._env = self
        self.event_source = EventSource()
        self.event_bus = EventBus()

    @classmethod
    def get_instance(cls):
        """
        返回已經建立的 Environment 物件
        """
        if Environment._env is None:
            raise RuntimeError(
                _(u"Environment has not been created. Please Use `Environment.get_instance()` after RQAlpha init"))
        return Environment._env

3.睡覺事件處理業務以及事件註冊

# -*- coding: utf-8 -*-

from env import  Environment
from event import EVENT

class sleep():
    def register_event(self, event_bus):
        event_bus = Environment.get_instance().event_bus
        event_bus.prepend_listener(EVENT.SLEEP, self._on_sleep)

    def _on_sleep(self, event):
        print('開始睡覺了')

4.吃飯事件業務處理及事件註冊

# -*- coding: utf-8 -*-
from env import  Environment
from event import EVENT

class eat():
    def register_event(self, event_bus):
        event_bus.prepend_listener(EVENT.EAT, self._on_eat)

    def _on_eat(self, event):
        print('開始吃晚飯了')

5.事件執行器加AOP:

# -*- coding: utf-8 -*-


from event import EVENT, Event


PRE_EAT = Event(EVENT.PRE_EAT)
POST_EAT = Event(EVENT.POST_EAT)
PRE_SLEEP = Event(EVENT.PRE_SLEEP)

class Executor(object):
    def __init__(self, env):
        self._env = env

    def run(self):

        event_bus = self._env.event_bus

        for event in self._env.event_source.events:
            if event.event_type == EVENT.EAT:
                event_bus.publish_event(PRE_EAT)
                event_bus.publish_event(event)
                event_bus.publish_event(POST_EAT)
            elif event.event_type == EVENT.SLEEP:
                event_bus.publish_event(PRE_SLEEP)
                event_bus.publish_event(event)
            else:
                event_bus.publish_event(event)
6.測試
# -*- coding: utf-8 -*-
from env import Environment
from  executor import Executor
from  event import Event, EVENT
from eat import eat
from sleep import  sleep
def test():

    env = Environment()
    #事件註冊
    eat().register_event(env.event_bus)
    sleep().register_event(env.event_bus)
    #事件發生
    env.event_source.add(Event(EVENT.EAT))
    env.event_source.add(Event(EVENT.SLEEP))
    #啟動事件驅動
    Executor(env).run()

test()
測試結果:




相關文章