详解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 获取文件列表(或是目录例表)
Mar 25 Python
python使用循环实现批量创建文件夹示例
Mar 25 Python
Python实现竖排打印传单手机号码易撕条
Mar 16 Python
Python的Bottle框架中返回静态文件和JSON对象的方法
Apr 30 Python
编写Python小程序来统计测试脚本的关键字
Mar 12 Python
浅谈django中的认证与登录
Oct 31 Python
Python中关于Sequence切片的下标问题详解
Jun 15 Python
Python实现确认字符串是否包含指定字符串的实例
May 02 Python
用Python实现筛选文件脚本的方法
Oct 27 Python
Tensorflow的梯度异步更新示例
Jan 23 Python
python中pop()函数的语法与实例
Dec 01 Python
Python基本的内置数据类型及使用方法
Apr 13 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
基于PHPexecl类生成复杂的报表表头示例
2016/10/14 PHP
javascript 装载iframe子页面,自适应高度
2009/03/20 Javascript
javascript 二维数组的实现与应用
2010/03/16 Javascript
JS通过相同的name进行表格求和代码
2013/08/18 Javascript
jQuery使用prepend()方法在元素前添加内容用法实例
2015/03/26 Javascript
jquery ajax 如何向jsp提交表单数据
2015/08/23 Javascript
jQuery Validate 数组 全部验证问题
2017/01/12 Javascript
js中删除数组中的某一元素实例(无下标时)
2017/02/28 Javascript
JS对象与JSON互转换、New Function()、 forEach()、DOM事件流等js开发基础小结
2017/08/10 Javascript
js截取字符串功能的实现方法
2017/09/27 Javascript
vue单页面打包文件大?首次加载慢?nginx带你飞,从7.5M到1.3M蜕变过程(推荐)
2018/01/16 Javascript
利用Node.js批量抓取高清妹子图片实例教程
2018/08/02 Javascript
vue悬浮可拖拽悬浮按钮的实例代码
2019/08/20 Javascript
2019最新21个MySQL高频面试题介绍
2020/02/06 Javascript
js实现带积分弹球小游戏
2020/07/21 Javascript
vue中watch和computed的区别与使用方法
2020/08/23 Javascript
基于JS实现快速读取TXT文件
2020/08/25 Javascript
[52:10]LGD vs Optic Supermajor小组赛D组胜者组决赛 BO3 第二场 6.3
2018/06/04 DOTA
[03:17]史诗级大片应援2018DOTA2国际邀请赛 致敬每一位坚守遗迹的勇士
2018/07/20 DOTA
跟老齐学Python之做一个小游戏
2014/09/28 Python
利用Python的装饰器解决Bottle框架中用户验证问题
2015/04/24 Python
python基于http下载视频或音频
2018/06/20 Python
django 连接数据库 sqlite的例子
2019/08/14 Python
使用pytorch实现可视化中间层的结果
2019/12/30 Python
解决python-docx打包之后找不到default.docx的问题
2020/02/13 Python
HTML5实现表单自动验证功能实例代码
2017/01/11 HTML / CSS
.net软件工程师应聘上机试题
2015/03/10 面试题
九年级化学教学反思
2014/01/28 职场文书
英语教师岗位职责
2014/03/16 职场文书
拓展策划方案
2014/06/03 职场文书
国家奖学金获奖感言
2014/08/16 职场文书
励志演讲稿3分钟
2014/08/21 职场文书
小学生优秀评语
2014/12/29 职场文书
稽核岗位职责范本
2015/04/13 职场文书
小学教师个人工作总结2015
2015/04/20 职场文书
导游词之台湾阿里山
2019/10/23 职场文书