详解Python的Flask框架中的signals信号机制


Posted in Python onJune 13, 2016

Flask 提供了信号(Signals)功能,是一种消息分发机制。类似于钩子(Hooks)。使用信号功能可以降低程序的耦合,分解复杂的业务模型。例如在更新了产品数据后,可以发送一个信号。当有需要对产品数据进行处理的功能时,就可以捕获信号进行处理。比如要建立产品缓存,或是更新搜索索引等。

定义信号

Flask 信号功能使用了 Blinker 模块,所以需要先安装 Blinker 模块

pip install blinker

定义一个信号:

from blinker import Namespace
product_saved = Namespace()

也可以使用 Flask 包装的 singles 对象:

from flask.singles import Namespace

发送信号

发送信号需要带上 app 实例方法,示例如下:

product_saved.send(app, product=product)

app 后面可以添加要传递的参数,但必须以 name=value 的格式,不支持使用单个变量名的方式。

收接信号

接收信号可以使用 connect_via 装饰器函数:

@product_saved.connect_via(app)
def updateCache(app, product):
  print(product)

Flask 中有以下核心信号:

1.flask.template_rendered

这个信号发送于一个模板被渲染成功后。信号传递的template是模板的实例,context是环境对象是一个字典。

订阅示例:

def log_template_renders(sender, template, context, **extra):
  sender.logger.debug('Rendering template "%s" with context %s',
            template.name or 'string template',
            context)
from flask import template_rendered
template_rendered.connect(log_template_renders, app)

2.flask.request_started

这个信号发送于请求开始之前,且请求环境设置完成之后。因为请求环境已经绑定, 所以订阅者可以用标准的全局代理,如 request 来操作请求。

订阅示例:

def log_request(sender, **extra):
  sender.logger.debug('Request context is set up')
from flask import request_started
request_started.connect(log_request, app)
flask.request_finished

这个信号发送于向客户端发送响应之前。信号传递的response为将要发送的响应。

订阅示例:

def log_response(sender, response, **extra):
  sender.logger.debug('Request context is about to close down. '
            'Response: %s', response)
from flask import request_finished
request_finished.connect(log_response, app)
flask.got_request_exception

这个信号发送于请求进行中发生异常的时候。它的发送 早于 标准异常处理介于。 在调试模式下,虽然没有异常处理,但发生异常时也发送这个信号。信号传递的exception是异常对象。

订阅示例:

def log_exception(sender, exception, **extra):
  sender.logger.debug('Got exception during processing: %s', exception)
from flask import got_request_exception
got_request_exception.connect(log_exception, app)
flask.request_tearing_down

这个信号发送于请求崩溃的时候,不管是否引发异常。目前,侦听此信号的函数在一般 崩溃处理器后调用,但是没有什么东西可用。

订阅示例:

def close_db_connection(sender, **extra):
  session.close()from flask import appcontext_tearing_down
request_tearing_down.connect(close_db_connection, app)

在 Flask 版本 0.9 中,这还会传递一个exc关键字参数,如果这个参数存在的话。 这个参数是引发崩溃的异常的引用。

3.flask.appcontext_tearing_down

当应用环境崩溃时发送这个信号。这个信号总是会发送,甚至是因为一个异常引发的 崩溃。侦听这个信号的函数会在常规崩溃处理器后被调用,但是你无法回馈这个信号。

订阅示例:

def close_db_connection(sender, **extra):
  session.close()from flask import request_tearing_down
appcontext_tearing_down.connect(close_db_connection, app)

这还会传递一个exc关键字参数,如果这个参数存在的话。这个参数是引发崩溃的 异常的引用。

4.flask.appcontext_pushed

当一个应用的环境被压入时,应用会发送这个信号。这个信号通常用于在单元测试中 临时钩接信息。例如可以用于改变g对象中现存的资源。

用法示例:

from contextlib import contextmanagerfrom
flask import appcontext_pushed
@contextmanagerdef user_set(app, user):
  def handler(sender, **kwargs):
    g.user = user
  with appcontext_pushed.connected_to(handler, app):
    yield

在测试代码中这样写:

def test_user_me(self):
  with user_set(app, 'john'):
    c = app.test_client()
    resp = c.get('/users/me')
    assert resp.data == 'username=john'
New in version 0.10.

5.appcontext_popped

当一个应用的环境被弹出时,应用会发送这个信号。这个信号通常写成appcontext_tearing_down 信号。

6.flask.message_flashed

当应用闪现一个消息时会发出这个信号。message`参数是消息内容, `category参数是消息类别。

订阅示例:

recorded = []def record(sender, message, category, **extra):
  recorded.append((message, category))
from flask import message_flashed
message_flashed.connect(record, app)

小结
信号可以让你在一瞬间安全地订阅它们。例如,这些临时的订阅对测试很有帮助。使用信号时,不要让信号订阅者(接收者)发生异常,因为异常会造成程序中断。

Python 相关文章推荐
几个提升Python运行效率的方法之间的对比
Apr 03 Python
python中global用法实例分析
Apr 30 Python
Python 判断是否为质数或素数的实例
Oct 30 Python
Python有序查找算法之二分法实例分析
Dec 11 Python
Python实现感知机(PLA)算法
Dec 20 Python
Python二叉搜索树与双向链表转换算法示例
Mar 02 Python
python序列化与数据持久化实例详解
Dec 20 Python
PyTorch使用cpu加载模型运算方式
Jan 13 Python
Python类的继承super相关原理解析
Oct 22 Python
详解python第三方库的安装、PyInstaller库、random库
Mar 03 Python
python 指定源路径来解决import问题的操作
Mar 04 Python
Python尝试实现蒙特卡罗模拟期权定价
Apr 21 Python
Python的Flask站点中集成xhEditor文本编辑器的教程
Jun 13 #Python
Flask的图形化管理界面搭建框架Flask-Admin的使用教程
Jun 13 #Python
Python的Flask框架中集成CKeditor富文本编辑器的教程
Jun 13 #Python
Linux中安装Python的交互式解释器IPython的教程
Jun 13 #Python
浅谈python中的面向对象和类的基本语法
Jun 13 #Python
深入理解python多进程编程
Jun 12 #Python
python中根据字符串调用函数的实现方法
Jun 12 #Python
You might like
实用PHP会员权限控制实现原理分析
2011/05/29 PHP
PHP分多步骤填写发布信息的简单方法实例代码
2012/09/23 PHP
深入php 正则表达式的学习探讨
2013/06/06 PHP
根据地区不同显示时间的javascript代码
2007/08/13 Javascript
jQuery asp.net 用json格式返回自定义对象
2010/04/07 Javascript
js每隔5分钟执行一次ajax请求的实现方法
2013/11/27 Javascript
js仿淘宝和百度文库的评分功能
2016/05/15 Javascript
Javascript删除指定元素节点的方法
2016/06/21 Javascript
JS实战篇之收缩菜单表单布局
2016/12/10 Javascript
js实现二级导航功能
2017/03/03 Javascript
NodeJS简单实现WebSocket功能示例
2018/02/10 NodeJs
详解从react转职到vue开发的项目准备
2019/01/14 Javascript
vue实现日历备忘录功能
2020/09/24 Javascript
微信小程序仿今日头条导航栏滚动解析
2019/08/20 Javascript
JavaScript实现背景自动切换小案例
2019/09/27 Javascript
vue 动态组件用法示例小结
2020/03/06 Javascript
Quasar Input:type="number" 去掉上下小箭头 实现加减按钮样式功能
2020/04/09 Javascript
js简单实现自动生成表格功能示例
2020/06/02 Javascript
[50:28]2018DOTA2亚洲邀请赛 3.31 小组赛 A组 Newbee vs KG
2018/04/01 DOTA
Pytorch抽取网络层的Feature Map(Vgg)实例
2019/08/20 Python
python树的同构学习笔记
2019/09/14 Python
Python多继承以及MRO顺序的使用
2019/11/11 Python
Django 路由层URLconf的实现
2019/12/30 Python
python批量处理txt文件的实例代码
2020/01/13 Python
IDLE下Python文件编辑和运行操作
2020/04/25 Python
Python如何输出百分比
2020/07/31 Python
python操作链表的示例代码
2020/09/27 Python
老师推荐信
2013/10/28 职场文书
如何写你的创业计划书
2014/01/07 职场文书
初中同学聚会感言
2014/02/11 职场文书
专科应届毕业生求职信
2014/06/04 职场文书
党员反对四风问题思想汇报
2014/09/12 职场文书
铣工实训报告
2014/11/05 职场文书
2014年后勤管理工作总结
2014/12/01 职场文书
走进科学观后感
2015/06/18 职场文书
师范生教育见习总结
2015/06/23 职场文书