python基于消息的编程

普通的编程方式是引用模块, 调用模块中的函数, 你需要知道模块名和函数名, 还要维护复杂的模块引用关系. 而如果基于消息的编程, 只需要订阅和发布消息即可, 降低了模块间的耦合性.
如下使用示例代码:

from Message import *
def greet(name): print(f"Hello {name}")
sub('greet',greet)
pub('greet','Joe')

具体实现参考了文章: python-message v0.2.x 全接触 https://blog.csdn.net/gzlaiyonghao/article/details/7215315
源码可下载: https://pypi.org/project/message/#files
我简化了实现代码并增加一些注释:

from collections import defaultdict as dd
from copy import copy

__all__ = [
		'Broker',	
		'sub',	
		'unsub',	
		'pub',	
		'declare',	
		'retract',	
		'get_declarations',	
		'has_declaration',	
		]	

class Broker:
    '''消息系统对象'''
    def __init__(self):
        self._router = dd(list)  # 存放topic及对应的回调函数, key为topic, value为回调函数的list
        self._board = {}	# 存放公告牌topic及对应调用参数
    def sub(self, topic:str, func:callable, front:bool = False):
        '''订阅指定的消息, 当消息触发时调用对应的回调函数. 其中front表示是否插入到最前面'''
        if func in self._router[topic]: return  # 不支持重复订阅
        # 确定是否插入最前面
        if front: self._router[topic].insert(0, func)
        else: self._router[topic].append(func)
        # 下面是公告牌的功能, 如果公告牌有此主题, 则立即触发回调函数
        if topic in self._board:
            a, kw = self._board[topic]
            func(*a, **kw)
    def unsub(self, topic:str, func:callable):
        '''取消订阅指定的消息'''
        if func not in self._router[topic]: return  # 不支持取消未订阅的消息
        try: self._router[topic].remove(func)
        except ValueError: pass # 移除不存在的函数也不报错
    def pub(self, topic:str, *a, **kw):
        '''发布消息, 调用所有订阅了此消息的回调函数'''
        # 使用copy的意思是在多线程的情况下也能够正常工作
        for func in copy(self._router[topic]): func(*a, **kw)
    def declare(self, topic:str, *a, **kw):
        '''发布公告牌, 存放回调函数所需要的参数'''
        self._board[topic] = (a, kw)
        self.pub(topic, *a, **kw)    # 立即发布消息
    def retract(self, topic:str):
        '''取消公告牌'''
        try:self._board.pop(topic)
        except KeyError:pass
    def get_declarations(self):
        '''获取所有发布的公告'''
        return self._board.keys()
    def has_declaration(self, topic:str):
        '''判断是否发布过公告'''
        return topic in self._board

_broker = Broker()
sub = _broker.sub
unsub = _broker.unsub
pub = _broker.pub
declare = _broker.declare
retract = _broker.retract
get_declarations = _broker.get_declarations
has_declaration = _broker.has_declaration

补充模块的__init__.py文件代码:

from .message import __all__
#__all__ = __all__
from .message import *
#print(__all__)
posted @ 2023-08-15 09:36  顺其自然,道法自然  阅读(22)  评论(0编辑  收藏  举报