信号机制

Flask中的信号机制(Signal)与操作系统中的信号机制类似,都是通过信号来通知已经注册的回调函数,并使回调函数开始运行的机制。在Flask中的信号机制由blinker库(官方推荐)提供支持,用于将函数注册到信号,并在触发信号时运行指定回调函数。信号机制主要用于将观察者模式中的各个模块之间解耦。

Flask定义了多个内置的信号,供应用监听特定事件,其中有一些是与请求钩子的触发位置相同,但是又有所不同。Flask内置的信号有以下这些:

  • template_rendered: 模板成功渲染后触发。
  • before_render_template: 模板渲染之前触发。
  • request_started: 请求被处理之前触发。
  • request_finished: 请求的响应被发送给客户端之后触发。
  • got_request_exception: 请求处理过程中发生异常的第一时间触发。
  • request_tearing_down: 请求被销毁时触发,无论是否存在异常都会触发。
  • appcontext_tearing_down: 应用上下文被销毁时触发。
  • appcontext_pushed: 应用上下文被Push时触发。
  • appcontext_popped: 应用上下文被Pop时触发。
  • message_flashed: 发送Flash信息时触发。

信号与请求钩子不同,信号不能中止请求,并且其调用是无序的,并且信号是可以携带参数的,而请求钩子通常不携带参数。信号与RabbitMQ之类的消息队列功能类似,但是更加轻型。RabbitMQ之类的消息队列能够实现的功能更多,并且可以在不同系统之间传递消息,而信号只是限于Flask应用中进行简单的消息分发。

订阅一个信号,可以使用以下基于修饰器的简单方式。

from flask import template_rendered

@template_rendered.connect_via(app)
def when_template_rendered(sender, template, context, **kwargs):
	pass

信号同样支持自定义,其需要用到blinker库中的signal类。信号的建立和订阅方式可参考下例。

from blinker import signal

# 实例化信号
sign = signal('test')

# 订阅信号
@sign.connect
def each(arg):
	pass

# 发送信号
sign.send(args)