Python 强大的信号库:blinker
一. 信号
大家好,我是老表~
信号是一种通知或者说通信的方式,信号分为发送方和接收方。发送方发送一种信号,接收方收到信号的进程会跳入信号处理函数,执行完后再跳回原来的位置继续执行。
常见的 Linux 中的信号,通过键盘输入 Ctrl+C,就是发送给系统一个信号,告诉系统退出当前进程。
信号的特点就是发送端通知订阅者发生了什么。使用信号分为 3 步:定义信号,监听信号,发送信号。
Python 中提供了信号概念的通信模块,就是blinker。
Blinker 是一个基于 Python 的强大的信号库,它既支持简单的点对点通信,也支持点对多点的组播。Flask 的信号机制就是基于它建立的。Blinker 的内核虽然小巧,但是功能却非常强大,它支持以下特性:
- 支持注册全局命名信号
- 支持匿名信号
- 支持自定义命名信号
- 支持与接收者之间的持久连接与短暂连接
- 通过弱引用实现与接收者之间的自动断开连接
- 支持发送任意大小的数据
- 支持收集信号接收者的返回值
- 线程安全
二. blinker 使用
安装方法:
pip install blinker
2.1 命名信号
from blinker import signal # 定义一个信号 s = signal('king') def animal(args): print('我是小钻风,大王回来了,我要去巡山') # 信号注册一个接收者 s.connect(animal) if "__main__" == __name__: # 发送信号 s.send()
2.2 匿名信号
blinker 也支持匿名信号,就是不需要指定一个具体的信号值。创建的每一个匿名信号都是互相独立的。
from blinker import Signal s = Signal() def animal(sender): print('我是小钻风,大王回来了,我要去巡山') s.connect(animal) if "__main__" == __name__: s.send()
2.3 组播信号
组播信号是比较能体现出信号优点的特征。多个接收者注册到信号上,发送者只需要发送一次就能传递信息到多个接收者。
from blinker import signal s = 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('大王叫我来巡山,抓个和尚做晚餐!')
2.4 接收方订阅主题
接受方支持订阅指定的主题,只有当指定的主题发送消息时才发送给接收方。这种方法很好的区分了不同的主题。
from blinker import signal s = signal('king') def animal(args): print(f'我是小钻风,{args} 是我大哥') s.connect(animal, sender='大象') if "__main__" == __name__: for i in ['狮子', '大象', '大鹏']: s.send(i)
2.5 装饰器用法
除了可以函数注册之外还有更简单的信号注册方法,那就是装饰器。
from blinker import signal s = signal('king') @s.connect def animal_one(args): print(f'我是小钻风,今天的口号是: {args}') @s.connect def animal_two(args): print(f'我是大钻风,今天的口号是: {args}') if "__main__" == __name__: s.send('大王叫我来巡山,抓个和尚做晚餐!')
2.6 可订阅主题的装饰器
connect的注册方法用着装饰器时有一个弊端就是不能够订阅主题,所以有更高级的connect_via方法支持订阅主题。
from blinker import signal s = signal('king') @s.connect_via('大象') def animal(args): print(f'我是小钻风,{args} 是我大哥') if "__main__" == __name__: for i in ['狮子', '大象', '大鹏']: s.send(i)
2.7 检查信号是否有接收者
如果对于一个发送者发送消息前要准备的耗时很长,为了避免没有接收者导致浪费性能的情况,所以可以先检查某一个信号是否有接收者,在确定有接收者的情况下才发送,做到精确。
from blinker import signal s = 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: <weakref at 0x10d02ae80; to 'function' at 0x10cedd430 (animal)>} 我是小钻风,大王回来了,我要去巡山 {} 孩儿们都出去巡山了
2.8 检查订阅者是否订阅了某个信号
也可以检查订阅者是否由某一个信号
from blinker import signal s = 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)
True False
三.基于 blinker 的 Flask 信号
Flask 集成 blinker 作为解耦应用的解决方案。在 Flask 中,信号的使用场景如:请求到来之前,请求结束之后。同时 Flask 也支持自定义信号。
3.1 简单 Flask demo
from flask import Flask app = 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。
3.2 自定义信号
因为 Flask 集成了信号,所以在 Flask 中使用信号时从 Flask 中引入。
from flask import Flask from flask.signals import _signals app = 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()
3.3 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 Flask from flask.signals import _signals, request_started import time app = 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的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

PS“正在载入”问题是由资源访问或处理问题引起的:硬盘读取速度慢或有坏道:使用CrystalDiskInfo检查硬盘健康状况并更换有问题的硬盘。内存不足:升级内存以满足PS对高分辨率图片和复杂图层处理的需求。显卡驱动程序过时或损坏:更新驱动程序以优化PS和显卡之间的通信。文件路径过长或文件名有特殊字符:使用简短的路径和避免使用特殊字符。PS自身问题:重新安装或修复PS安装程序。

PS启动时卡在“正在载入”可能是由于各种原因造成的:禁用损坏或冲突的插件。删除或重命名损坏的配置文件。关闭不必要的程序或升级内存,避免内存不足。升级到固态硬盘,加快硬盘读取速度。重装PS修复损坏的系统文件或安装包问题。查看错误日志分析启动过程中的错误信息。

PS打开文件时出现“正在载入”卡顿,原因可能包括:文件过大或损坏、内存不足、硬盘速度慢、显卡驱动问题、PS版本或插件冲突。解决方法依次为:检查文件大小和完整性、增加内存、升级硬盘、更新显卡驱动、卸载或禁用可疑插件、重装PS。通过逐步排查,并善用PS的性能设置,养成良好的文件管理习惯,可以有效解决该问题。

文章介绍了MySQL数据库的上手操作。首先,需安装MySQL客户端,如MySQLWorkbench或命令行客户端。1.使用mysql-uroot-p命令连接服务器,并使用root账户密码登录;2.使用CREATEDATABASE创建数据库,USE选择数据库;3.使用CREATETABLE创建表,定义字段及数据类型;4.使用INSERTINTO插入数据,SELECT查询数据,UPDATE更新数据,DELETE删除数据。熟练掌握这些步骤,并学习处理常见问题和优化数据库性能,才能高效使用MySQL。

羽化控制的关键在于理解其渐变本质。PS本身不提供直接控制渐变曲线的选项,但你可以通过多次羽化、配合蒙版、精细选区,灵活调整半径和渐变柔和度,实现自然过渡效果。

MySQL性能优化需从安装配置、索引及查询优化、监控与调优三个方面入手。1.安装后需根据服务器配置调整my.cnf文件,例如innodb_buffer_pool_size参数,并关闭query_cache_size;2.创建合适的索引,避免索引过多,并优化查询语句,例如使用EXPLAIN命令分析执行计划;3.利用MySQL自带监控工具(SHOWPROCESSLIST,SHOWSTATUS)监控数据库运行状况,定期备份和整理数据库。通过这些步骤,持续优化,才能提升MySQL数据库性能。

MySQL 有免费的社区版和收费的企业版。社区版可免费使用和修改,但支持有限,适合稳定性要求不高、技术能力强的应用。企业版提供全面商业支持,适合需要稳定可靠、高性能数据库且愿意为支持买单的应用。选择版本时考虑的因素包括应用关键性、预算和技术技能。没有完美的选项,只有最合适的方案,需根据具体情况谨慎选择。

PS卡在载入界面可能是由软件自身(文件损坏或插件冲突)、系统环境(驱动过时或系统文件损坏)或硬件(硬盘损坏或内存条故障)问题造成的。首先检查计算机资源是否充足,关闭后台程序释放内存和CPU资源。修复PS安装或检查插件是否存在兼容性问题。更新或回退PS版本。检查显卡驱动并更新,运行系统文件检查。若排除上述问题,则可以尝试硬盘检测和内存测试。
