9.flask信号(能自定义的扩展点)
1.什么是信号?
一般是框架内的高级用法
是一个钩子,当执行到。。。的时候,就自动执行。。。方法或者函数,让我们可以进行一些自定义的操作
2.flask中有关的信号(扩展点)
根据请求的先后的顺序--视图函数未执行之前
中间件
app.wsgi_app = MyMiddleware(app.wsgi_app)
将函数注册到appcontext_pushed信号里面,当将app_ctx对象加入到栈之后,会触发该信号
appcontext_pushed.send(self.app),也就是执行完这句代码之后会触发f1函数
在AppConttext类里面

from flask import Flask,render_template app = Flask(__name__) @app.route('/index') def index(): return render_template('index.html') @app.route('/order') def order(): return render_template('order.html') class MyMiddleware(object): def __init__(self,old_app): self.wsgi_app = old_app.wsgi_app def __call__(self, *args, **kwargs): print('123') result = self.wsgi_app(*args, **kwargs) print('456') return result app.wsgi_app = MyMiddleware(app) if __name__ == '__main__': app.run()
信号.appcontext_pushed.send
是由app_ctx.push()来触发的
当app_ctx被push到local中栈之后,会触发appcontext_pushed信号,之前注册在这个信号中的方法,就会被执行。

from flask import Flask,render_template from flask import signals app = Flask(__name__) @signals.appcontext_pushed.connect def f1(arg): print('appcontext_pushed信号f1被触发',arg) @signals.appcontext_pushed.connect def f2(arg): print('appcontext_pushed信号f2被触发',arg) @app.route('/index') def index(): return render_template('index.html') @app.route('/order') def order(): return render_template('order.html') if __name__ == '__main__': app.run() # app.__call__
装饰器.before_first_request
由self.try_trigger_before_first_request_functions()来触发的

from flask import Flask,render_template app = Flask(__name__) @app.before_first_request def f2(): print('before_first_requestf2被触发') @app.route('/index') def index(): return render_template('index.html') @app.route('/order') def order(): return render_template('order.html') if __name__ == '__main__': app.run()
信号.request_started
由 request_started.send(self)来触发

from flask import Flask,render_template from flask import signals app = Flask(__name__) @signals.request_started.connect def f3(arg): print('request_started信号被触发',arg) @app.route('/index') def index(): return render_template('index.html') @app.route('/order') def order(): return render_template('order.html') if __name__ == '__main__': app.run()
self.preprocess_request() 里面有两个扩展点(url_value_preprocessor和before_request)
装饰器.url_value_preprocessor
执行url_value_preprocessor,由funcs = self.url_value_preprocessors.get(None, ())来触发的

from flask import Flask,render_template,g from flask import signals app = Flask(__name__) @app.url_value_preprocessor def f5(endpoint,args): print('f5') @app.route('/index/') def index(): print('index') return render_template('index.html') @app.route('/order') def order(): print('order') return render_template('order.html') if __name__ == '__main__': app.run()
装饰器.before_request
执行before_request,由funcs = self.before_request_funcs.get(None, ())来触发的

from flask import Flask,render_template,g from flask import signals app = Flask(__name__) @app.before_request def f6(): g.xx = 123 print('f6') @app.route('/index/') def index(): print('index') return render_template('index.html') @app.route('/order') def order(): print('order') return render_template('order.html') if __name__ == '__main__': app.run()
根据请求的先后的顺序--视图函数执行时
信号.before_render_template和信号template_rendered
return render_template('index.html')里面也有可扩展的信号,是在视图函数最后一步,也就是给用户返回信息的时候 render_template源码 def _render(template, context, app): """Renders the template and fires the signal""" # 模板渲染之前 before_render_template.send(app, template=template, context=context) # 模板渲染 rv = template.render(context) # 模板渲染之后 template_rendered.send(app, template=template, context=context) return rv # template是模板路经,context是返回时传递的参数

from flask import Flask,render_template,g from flask import signals app = Flask(__name__) @signals.before_render_template.connect def f7(app, template, context): print('f7') @signals.template_rendered.connect def f8(app, template, context): print('f8') @app.route('/index/') def index(): return render_template('index.html') @app.route('/order') def order(): print('order') return render_template('order.html') if __name__ == '__main__': app.run()
finalize_request里面有两个扩展点(after_request和request_finished)
装饰器.after_request
执行after_request,由response = self.process_response(response)来触发的

from flask import Flask,render_template,g from flask import signals app = Flask(__name__) @app.after_request def f9(response): print('f9') return response @app.route('/index/') def index(): return render_template('index.html') @app.route('/order') def order(): print('order') return render_template('order.html') if __name__ == '__main__': app.run()
信号.request_finished
执行request_finished,由request_finished.send(self, response=response)来触发的

from flask import Flask,render_template,g from flask import signals app = Flask(__name__) @signals.request_finished.connect def f10(app,response): print('f10') @app.route('/index/') def index(): return render_template('index.html') @app.route('/order') def order(): print('order') return render_template('order.html') if __name__ == '__main__': app.run()
根据请求的先后的顺序--视图函数执行之后,异常处理阶段
信号.got_request_exception
执行got_request_exception,由flask中的源码部分出现异常才会捕获,因为在源码部分有的没有做异常处理,而在试图阶段都做了异常处理
比如在request_first阶段就没有异常处理(源码中没有异常处理的都可以捕获的到)
注意:
在flask源码出现异常的时候,after_request和request_finished的扩展点可会执行一遍

from flask import Flask,render_template,g from flask import signals app = Flask(__name__) @app.before_first_request def test(): int('asdf') @signals.got_request_exception.connect def f11(app,exception): print('f11') @app.route('/index/') def index(): return render_template('index.html') @app.route('/order') def order(): print('order') return render_template('order.html') if __name__ == '__main__': app.run()
根据请求的先后的顺序--视图函数执行之后,垃圾回收阶段
ctx.auto_pop(error)垃圾回收阶段有两个扩展点(teardown_request和request_tearing_down)
装饰器.teardown_request
执行teardown_request,由ctx.auto_pop(error)触发,里面的self.pop(exc)的 self.app.do_teardown_request(exc)函数。
是在请求结束之后无论成功与否,都想执行的功能,是在auto_pop之前执行.
在self.app.do_teardown_request(exc)阶段也会触发一个信号
信号request_tearing_down.send(self, exc=exc)

from flask import Flask,render_template,g from flask import signals app = Flask(__name__) @app.teardown_request def f12(exc): print('f12') @app.route('/index/') def index(): return render_template('index.html') @app.route('/order') def order(): print('order') return render_template('order.html') if __name__ == '__main__': app.run()
信号.request_tearing_down

from flask import Flask,render_template,g from flask import signals app = Flask(__name__) @signals.request_tearing_down.connect def f13(app,exc): print('f13') @app.route('/index/') def index(): return render_template('index.html') @app.route('/order') def order(): print('order') return render_template('order.html') if __name__ == '__main__': app.run()
信号.appcontext_popped.send
appcontext对象删除之后做的事情

from flask import Flask,render_template,g from flask import signals app = Flask(__name__) @signals.appcontext_popped.connect def f14(app): print('f14') @app.route('/index/') def index(): return render_template('index.html') @app.route('/order') def order(): print('order') return render_template('order.html') if __name__ == '__main__': app.run()
信号.message_flashed
基于session实现的用于保存数据的集合,特点是:存放的值,只能使用一次,然后就删除。在里面赋值的时候会触发message_flashed信号

from flask import Flask,render_template,flash,get_flashed_messages,session from flask import signals app = Flask(__name__) app.secret_key = 'iuknsoiuwknlskjdf' @app.route('/index/') def index(): # flash('123') session['k1'] = 123 return render_template('index.html') @app.route('/order') def order(): # messages = get_flashed_messages() # print(messages) val = session['k1'] del session['k1'] print(val) return render_template('order.html') if __name__ == '__main__': app.run()
总结:
总结: 关于flask内部共有14+个扩展点用于我们对flask框架内部进行定制,其中有:9个是信号,其他的是5个装饰器 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") # 基于session实现的用于保存数据的集合,特点是:存放的值,只能使用一次,然后就删除。在里面赋值的时候会触发message_flashed信号
from flask import signals里面可以查看全部的信号和扩展点
pass
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· AI与.NET技术实操系列(六):基于图像分类模型对图像进行分类