Flask信号


信号 ---- 在满足某种情况下会触发某个函数的执行

信号与请求拓展的区别

信号可以触发一个或者多个绑定函数的执行,同时可以有返回值,而请求拓展的返回值是被严格限制的

信号的绑定程序的执行是按照绑定是的先后顺序执行的

使用信号触发和直接调用的区别

信号触发绑定函数的执行是在他自己的调用栈进行,而直接调用是在 flask 的请求上下文和全局上下文中进行的;这就意味着信号触发执行的时候是访问不到请求上下文和g对象

所以必要时,可以使用 flask 提供的请求上下文管理工具。


信号源码的说明

其实,从源码中可以看出,Namespace这个类会先尝试从blinker模块中导入’

如果导不到,就会使用下面自己写的Namespace

文件中间说明了_signals = Namespace(),所以使用这两个中的哪一个都行;

使用_signals有一个单例模式的效果,所以尽量使用这个,保证一个项目中就一个总的信号触发机制

文件最下方初始化了很多内置信号

import typing as t

try:
  from blinker import Namespace

  signals_available = True
except ImportError:
	signals_available = False

  class Namespace: # type: ignore
    def signal(self, name: str, doc: t.Optional[str] = None) -> "_FakeSignal":
    	return _FakeSignal(name, doc)

	class _FakeSignal:
    """If blinker is unavailable, create a fake class with the same
    interface that allows sending of signals but will fail with an
    error on anything else. Instead of doing anything on send, it
    will just ignore the arguments and do nothing instead.
    """

    def __init__(self, name: str, doc: t.Optional[str] = None) -> None:
      self.name = name
      self.__doc__ = doc

    def send(self, *args: t.Any, **kwargs: t.Any) -> t.Any:
    	pass

    def _fail(self, *args: t.Any, **kwargs: t.Any) -> t.Any:
      raise RuntimeError(
      "Signalling support is unavailable because the blinker"
      " library is not installed."
      ) from None

    connect = connect_via = connected_to = temporarily_connected_to = _fail
    disconnect = _fail
    has_receivers_for = receivers_for = _fail
    del _fail


# The namespace for code signals. If you are not Flask code, do
# not put signals in here. Create your own namespace instead.
_signals = Namespace()


# Core signals. For usage examples grep the source code or consult
# the API documentation in docs/api.rst as well as docs/signals.rst
template_rendered = _signals.signal("template-rendered")
before_render_template = _signals.signal("before-render-template")
request_started = _signals.signal("request-started")
request_finished = _signals.signal("request-finished")
request_tearing_down = _signals.signal("request-tearing-down")
got_request_exception = _signals.signal("got-request-exception")
appcontext_tearing_down = _signals.signal("appcontext-tearing-down")
appcontext_pushed = _signals.signal("appcontext-pushed")
appcontext_popped = _signals.signal("appcontext-popped")
message_flashed = _signals.signal("message-flashed")

内置信号说明

内置信号会自动触发

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')                # 调用flash在其中添加数据时,自动触发

 

内置信号的使用

使用步骤:

第一步:写个函数–必须接受一些参数
第二步:跟信号绑定
第三步:触发信号

from flask import Flask, render_template
from flask import signals

app = Flask(__name__)


# 内置信号使用步骤
# 第一步:写个函数
def render_before(*args,**kwargs):
    print(args)
    print(kwargs)
    print('模板要渲染了')


# 第二步:跟信号绑定
signals.before_render_template.connect(render_before)


# 第三步:触发信号 (内置信号,会自动触发)

@app.route('/')
def index():
    print('index 执行了')
    return render_template('index.html', name='刘亦菲')


if __name__ == '__main__':
    app.run()

 

自定义信号

不会自动触发,只能手动触发,通过send方法

第一步:定义信号
第二步:写个函数
第三步:跟信号绑定
第四步:触发信号—指定触发时给绑定函数传递的参数

from flask import Flask, render_template,request
from flask import signals
from flask.signals import _signals

app = Flask(__name__)


# 第一步:定义信号
xxx = _signals.signal('xxx')

# 第二步:写个函数
def add(*args, **kwargs):
    print(args)
    print(kwargs)
    print('add执行了')

# 第三步:跟信号绑定
xxx.connect(add)

#第四步:触发信号
@app.route('/')
def index():
    xxx.send(request=request)
    print('index 执行了')
    return render_template('index.html', name='刘亦菲')


if __name__ == '__main__':
    app.run()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值