Flask Signals 信号 API
Flask 使用 Blinker 库在关键事件发生时发送信号。你可以连接这些信号来执行额外的日志记录、监控等操作。
信号并非 Flask 的核心功能——大部分需求通过钩子(before_request 等)即可满足。
核心请求信号
| 信号 | 触发时机 | 传递的参数 |
|---|---|---|
| request_started | 请求上下文建立后、预处理之前 | sender=app |
| request_finished | 响应构建完成后、发送之前 | sender=app, response |
| got_request_exception | 请求过程中发生未处理的异常 | sender=app, exception |
| request_tearing_down | 请求上下文销毁时(始终执行) | sender=app, exc(可选) |
应用上下文信号
| 信号 | 触发时机 | 传递的参数 |
|---|---|---|
| appcontext_pushed | 应用上下文推入栈时 | sender=app |
| appcontext_popped | 应用上下文弹出栈时 | sender=app |
| appcontext_tearing_down | 应用上下文销毁时(始终执行) | sender=app, exc(可选) |
模板和消息信号
| 信号 | 触发时机 | 传递的参数 |
|---|---|---|
| template_rendered | 模板渲染成功时 | sender=app, template, context |
| before_render_template | 模板渲染之前 | sender=app, template, context |
| message_flashed | 调用 flash() 时 | sender=app, message, category |
连接信号的方式
| 方式 | 说明 |
|---|---|
| signal.connect(func, app) | 直接连接信号。func 接收 sender 和关键字参数 |
| signal.connect_via(app)(func) | 装饰器形式。自动将 app 作为 sender |
| with signal.connected_to(func, app): | 上下文管理器。临时连接信号 |
代码示例
实例
from flask import Flask, request_started, request_finished, template_rendered
app = Flask(__name__)
# 方式1:直接连接
def log_request_start(sender, **extra):
print(f"Request started on {sender.name}")
request_started.connect(log_request_start, app)
# 方式2:装饰器连接
@request_finished.connect_via(app)
def log_request_end(sender, response, **extra):
print(f"Request finished with status {response.status_code}")
# 方式3:模板渲染信号
@template_rendered.connect_via(app)
def log_template(sender, template, context, **extra):
print(f"Template rendered: {template.name}")
# 方式4:捕获异常
from flask import got_request_exception
def log_error(sender, exception, **extra):
sender.logger.error(f"Exception: {exception}")
got_request_exception.connect(log_error, app)
app = Flask(__name__)
# 方式1:直接连接
def log_request_start(sender, **extra):
print(f"Request started on {sender.name}")
request_started.connect(log_request_start, app)
# 方式2:装饰器连接
@request_finished.connect_via(app)
def log_request_end(sender, response, **extra):
print(f"Request finished with status {response.status_code}")
# 方式3:模板渲染信号
@template_rendered.connect_via(app)
def log_template(sender, template, context, **extra):
print(f"Template rendered: {template.name}")
# 方式4:捕获异常
from flask import got_request_exception
def log_error(sender, exception, **extra):
sender.logger.error(f"Exception: {exception}")
got_request_exception.connect(log_error, app)
