千家信息网

如何使用python中的信号通信blinker

发表于:2024-11-11 作者:千家信息网编辑
千家信息网最后更新 2024年11月11日,这篇文章主要介绍"如何使用python中的信号通信blinker",在日常操作中,相信很多人在如何使用python中的信号通信blinker问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法
千家信息网最后更新 2024年11月11日如何使用python中的信号通信blinker

这篇文章主要介绍"如何使用python中的信号通信blinker",在日常操作中,相信很多人在如何使用python中的信号通信blinker问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"如何使用python中的信号通信blinker"的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

信号:

信号是一种通知或者说通信的方式,信号分为发送方和接收方。发送方发送一中信号,接收方收到信号的进程会跳入信号处理函数,执行完后再跳回原来的位置继续执行。常见的linux中的信号,通过键盘输入Ctrl+C,就是发送给系统一个信号,告诉系统退出当前进程。

信号的特点就是发送端通知订阅者发生了什么。使用信号分为3步,定义信号,监听信号,发送信号

python中提供了信号概念的通信模块,就是blinker

官方介绍:

Blinker 是一个基于Python的强大的信号库,它既支持简单的点对点通信,也支持点对多点的组播。Flask的信号机制就是基于它建立的。Blinker的内核虽然小巧,但是功能却非常强大,它支持以下特性:

  • 支持注册全局命名信号

  • 支持匿名信号

  • 支持自定义命名信号

  • 支持与接收者之间的持久连接与短暂连接

  • 通过弱引用实现与接收者之间的自动断开连接

  • 支持发送任意大小的数据

  • 支持收集信号接收者的返回值

  • 线程安全

blinker 使用

安装方法:

pip install blinker

命名信号

from blinker import signal# 定义一个信号s = signal('king')def animal(args):    print('我是小钻风,大王回来了,我要去巡山')# 信号注册一个接收者s.connect(animal)if "__main__" == __name__:    # 发送信号    s.send()

匿名信号

blinker也支持匿名信号,就是不需要指定一个具体的信号值。创建的每一个匿名信号都是互相独立的。

from blinker import Signals = Signal()def animal(sender):    print('我是小钻风,大王回来了,我要去巡山')s.connect(animal)if "__main__" == __name__:    s.send()

组播信号

组播信号是比较能体现出信号优点的特征。多个接收者注册到信号上,发送者只需要发送一次就能传递信息到多个接收者。

from blinker import signals = signal('king')def animal_one(args):    print(f'我是小钻风,今天的口号是: {args}')def animal_two(args):    print(f'我是大钻风,今天的口号是: {args}')s.connect(animal_one)s.connect(animal_two)if "__main__" == __name__:    s.send('大王叫我来巡山,抓个和尚做晚餐!')

接收方订阅主题

接受方支持订阅指定的主题,只有当指定的主题发送消息时才发送给接收方。这种方法很好的区分了不同的主题。

from blinker import signals = signal('king')def animal(args):    print(f'我是小钻风,{args} 是我大哥')s.connect(animal, sender='大象')if "__main__" == __name__:    for i in ['狮子', '大象', '大鹏']:        s.send(i)

装饰器用法

除了可以函数注册之外还有更简单的信号注册方法,那就是装饰器。

from blinker import signals = signal('king')@s.connectdef animal_one(args):    print(f'我是小钻风,今天的口号是: {args}')@s.connectdef animal_two(args):    print(f'我是大钻风,今天的口号是: {args}')if "__main__" == __name__:    s.send('大王叫我来巡山,抓个和尚做晚餐!')

可订阅主题的装饰器

connect的注册方法用着装饰器时有一个弊端就是不能够订阅主题,所以有更高级的connect_via方法支持订阅主题。

from blinker import signals = signal('king')@s.connect_via('大象')def animal(args):    print(f'我是小钻风,{args} 是我大哥')if "__main__" == __name__:    for i in ['狮子', '大象', '大鹏']:        s.send(i)

检查信号是否有接收者

如果对于一个发送者发送消息前要准备的耗时很长,为了避免没有接收者导致浪费性能的情况,所以可以先检查某一个信号是否有接收者,在确定有接收者的情况下才发送,做到精确。

from blinker import signals = signal('king')q = signal('queue')def animal(sender):    print('我是小钻风,大王回来了,我要去巡山')s.connect(animal)if "__main__" == __name__:        res = s.receivers    print(res)    if res:        s.send()        res = q.receivers    print(res)    if res:        q.send()    else:        print("孩儿们都出去巡山了")
{4511880240: }我是小钻风,大王回来了,我要去巡山{}孩儿们都出去巡山了

检查订阅者是否订阅了某个信号

也可以检查订阅者是否由某一个信号

from blinker import signals = signal('king')q = signal('queue')def animal(sender):    print('我是小钻风,大王回来了,我要去巡山')s.connect(animal)if "__main__" == __name__:        res = s.has_receivers_for(animal)    print(res)    res = q.has_receivers_for(animal)    print(res)
TrueFalse

基于blinker的Flask信号

Flask集成blinker作为解耦应用的解决方案。在Flask中,信号的使用场景如:请求到来之前,请求结束之后。同时Flask也支持自定义信号。

简单 Flask demo

from flask import Flaskapp = Flask(__name__)@app.route('/',methods=['GET','POST'],endpoint='index')def index():    return 'hello blinker'if __name__ == '__main__':    app.run()

访问127.0.0.1:5000时,返回给浏览器hello blinker

自定义信号

因为flask集成了信号,所以在flask中使用信号时从flask中引入。

from flask.signals import _signals
from flask import Flaskfrom flask.signals import _signalsapp = Flask(__name__)s = _signals.singal('msg')def QQ(args):    print('you have msg from QQ')s.connect(QQ)@app.route('/',methods=['GET','POST'],endpoint='index')def index():    s.send()    return 'hello blinker'if __name__ == '__main__':    app.run()

Flask自带信号

在Flask中除了可以自定义信号,还可以使用自带信号。Flask中自带的信号有很多种,具体如下:

请求request_started = _signals.signal('request-started')                # 请求到来前执行request_finished = _signals.signal('request-finished')              # 请求结束后执行 模板渲染before_render_template = _signals.signal('before-render-template')  # 模板渲染前执行template_rendered = _signals.signal('template-rendered')            # 模板渲染后执行 请求执行got_request_exception = _signals.signal('got-request-exception')    # 请求执行出现异常时执行request_tearing_down = _signals.signal('request-tearing-down')      # 请求执行完毕后自动执行(无论成功与否)appcontext_tearing_down = _signals.signal('appcontext-tearing-down') # 请求上下文执行完毕后自动执行(无论成功与否) 请求上下文中appcontext_pushed = _signals.signal('appcontext-pushed')            # 请求上下文push时执行appcontext_popped = _signals.signal('appcontext-popped')            # 请求上下文pop时执行message_flashed = _signals.signal('message-flashed')                # 调用flask在其中添加数据时,自动触发

下面以请求到来之前为例,看flask中信号如何使用

from flask import Flaskfrom flask.signals import _signals, request_startedimport timeapp = Flask(__name__)def wechat(args):    print('you have msg from wechat')# 从flask中引入已经定好的信号,注册一个函数request_started.connect(wechat)@app.route('/',methods=['GET','POST'],endpoint='index')def index():    return 'hello blinker'if __name__ == '__main__':    app.run()

当请求到来时,flask会经过request_started 通知接受方,就是函数wechat,这时wechat函数先执行,然后才返回结果给浏览器。

但这种使用方法并不是很地道,因为信号并不支持异步方法,所以通常在生产环境中信号的接收者都是配置异步执行的框架,如python中大名鼎鼎的异步框架celery。

总结

信号的优点:

  • 解耦应用:将串行运行的耦合应用分解为多级执行

  • 发布订阅者:减少调用者的使用,一次调用通知多个订阅者

信号的缺点:

  • 不支持异步

  • 支持订阅主题的能力有限

到此,关于"如何使用python中的信号通信blinker"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!

信号 支持 订阅 接收者 小钻 主题 就是 方法 通信 大王 函数 我要 订阅者 上下 上下文 口号 大象 收方 学习 多个 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 爱云淘泰安网络技术有限公司 惠普服务器风扇调速 文件传至云服务器失败是什么意思 贵州省网络安全知识竞答入口 数据库的安全保密设计方法 网络安全中职演讲稿 杭州临安区软件开发app 瑞牛网络技术有限公司 网络安全工程师英文翻译 怎么从服务器ilo口远程 关系型数据库管理系统是哪个 诺克萨斯的服务器 常熟无忧网络技术专业服务 计算机网络技术招聘信息 网络安全职业金字塔 mysql数据库导出存放 钦州民宿软件开发 准备计算机三级数据库 知道服务器的ip 泰拉瑞亚旅行服务器ip 数据库字段添加标题怎么弄 软件开发产品部kpi指标 太原学校大屏触摸软件开发公司 松岗互助软件开发 网络安全机密与解决方案 猫和老鼠的服务器是土豆 数据库的工作是做什么 针对服务器安全有哪些防护策略 吉林最新网络安全 创建数据库有数据文件日志文件
0