flask学习笔记(十九) --信号机制

本文介绍Flask中的信号机制,适合菜鸟入门理解

  • 理解信号机制的概念以及应用

  • 如何定义一个信号、订阅(监听)一个信号、发送一个信号

  • Flask内置的信号



一、什么是信号

什么是信号?信号通过发送发生在核心框架的其它地方或 Flask 扩展的动作 时的通知来帮助你解耦应用。简而言之,信号允许特定的发送端通知订阅者发 生了什么。

                                                            flask中文手册

其实这里的信号就是日常理解的信号,只是一种信息标号,它本身没有什么特殊含义。我们会事先约定好信号的的含义(定义信号)。通常我们说的监听信号,是服务器监听信号会什么时候发生;这里使用订阅是相对我们而言的(因为信号最终是要反映给我们人看的),像订阅公众号一样订阅信号,当这类信号发生时,我们知道发生了什么,那我们可以知道接下来该做什么了。而Flask信号(signals, or event hooking)允许特定的发送端通知订阅者发生了什么。

信号依赖于Blinker库

具体请参考手册:http://docs.pythontab.com/flask/flask0.10/signals.html


信号似乎和一些内置的 装饰器做同样的事(如:request_started 与 before_request() 十分相似)。然而它们工作的方式是有 差异的。

回顾一下之前学习的钩子函数(修饰器的一种):

Flask钩子(通常出现在蓝图或应用程序现存的方法中,比如一些内置装饰器,例如before_request)不需要Blinker库并且允许你改变请求对象(request)或者响应对象(response)。这些改变了应用程序(或者蓝图)的行为。比如before_request()装饰器。

信号看起来和钩子做同样的事情。然而在工作方式上它们存在不同。譬如核心的before_request()处理程序以特定的顺序执行,并且可以在返回响应之前放弃请求。相比之下,所有的信号处理器是无序执行的,并且不修改任何数据。

一般来说,钩子用于改变行为(比如,身份验证或错误处理),而信号用于记录事件(比如记录日志)。


二、flask中操作规范

2.1  定义信号

定义信号需要使用到blinker这个包的Namespace类来创建一个命名空间,然后创建一个新信号。比如定义一个在访问了某个视图函数的时候的信号。

# Namespace的作用:为了防止多人开发的时候,信号名字冲突的问题
from blinker import Namespace  
zlspace = Namespace()
fire_signal = zlspace.signal('fire')



2.2 订阅信号

订阅(监听)信号使用singal对象的connect方法,在这个方法中需要传递一个函数,用来接收以后监听到这个信号该做的事情。

def fire_bullet(sender):
print(sender)
print('start fire bullet')
fire_signal.connect(fire_bullet)


2.3 发送信号

发送信号使用singal对象的send方法,这个方法可以传递一些其他参数过去。

fire_signal.send()



三、关于Flask内置的信号

1. template_rendered:模版渲染完成后的信号。

2. before_render_template:模版渲染之前的信号。

3. request_started:模版开始渲染。

4. request_finished:模版渲染完成。

5. request_tearing_down:request对象被销毁的信号。

6. got_request_exception:视图函数发生异常的信号。一般可以监听这个信号,来记录网站异常信息。

7. appcontext_tearing_down:app上下文被销毁的信号。

8. appcontext_pushed:app上下文被推入到栈上的信号。

9. appcontext_popped:app上下文被推出栈中的信号

10. message_flashed:调用了Flask的`flashed`方法的信号。


与自定义信号的使用方法一致

from flask import got_request_exception
def request_exception_log(sender,exception):
print(exception)
got_request_exception.connect(request_exception_log)

@app.route('/')
def hello_world():
a = 1/0
   
return render_template('index.html')

访问hello_world视图函数,服务器发出一个异常信号,再经过flask内置信号机制到request_exception_log()函数处理,打印异常信息!


参考文章:https://blog.csdn.net/mapleandkw/article/details/42492363

flask中文手册:http://docs.pythontab.com/flask/flask0.10/

猜你喜欢

转载自blog.csdn.net/feit2417/article/details/80735643
今日推荐