python框架之Flask(5)-@app.before_request原理
示例
from flask import Flask app = Flask(__name__) @app.before_request
def xx():
pass @app.route('/')
def index():
return 'index' if __name__ == '__main__':
app.run()
看如上代码,如果此时请求视图函数 index ,在视图函数执行之前, @app.before_request 装饰的函数在这里也就是 xx 会先执行。
源码
查看 before_request :
@setupmethod
def before_request(self, f):
self.before_request_funcs.setdefault(None, []).append(f)
return f
flask.app.Flask.before_request
首先要知道在脚本加载时,被装饰器装饰的函数会被作为参数传入装饰器函数,在上面示例中也就是会将 xx 函数作为 before_request 函数的参数 f 传入。可以看到该装饰器函数就很简单两行,把函数 f 句柄添加到 app.before_request_funcs 列表中,对应示例中就是将 xx 函数的句柄添加到了 before_request_funcs 中。
紧接着,在请求到来时,会执行 app.wsgi_app 方法:
def wsgi_app(self, environ, start_response):
ctx = self.request_context(environ)
error = None
try:
try:
ctx.push()
response = self.full_dispatch_request()
except Exception as e:
error = e
response = self.handle_exception(e)
except:
error = sys.exc_info()[1]
raise
return response(environ, start_response)
finally:
if self.should_ignore_error(error):
error = None
ctx.auto_pop(error)
flask.app.Flask.wsgi_app
进到第 7 行的 full_dispatch_request 方法:
def full_dispatch_request(self):
self.try_trigger_before_first_request_functions()
try:
request_started.send(self)
rv = self.preprocess_request()
if rv is None:
rv = self.dispatch_request()
except Exception as e:
rv = self.handle_user_exception(e)
return self.finalize_request(rv)
flask.app.Flask.full_dispatch_request
再进到第 5 行的 preprocess_request 方法:
def preprocess_request(self):
bp = _request_ctx_stack.top.request.blueprint funcs = self.url_value_preprocessors.get(None, ())
if bp is not None and bp in self.url_value_preprocessors:
funcs = chain(funcs, self.url_value_preprocessors[bp])
for func in funcs:
func(request.endpoint, request.view_args) funcs = self.before_request_funcs.get(None, ())
if bp is not None and bp in self.before_request_funcs:
funcs = chain(funcs, self.before_request_funcs[bp])
for func in funcs:
rv = func()
if rv is not None:
return rv
flask.app.Flask.preprocess_request
看到第 10 行,从 self.before_request_funcs 拿到之前存入的方法,也就是也就是上面被 before_request 装饰器装饰的函数对应示例中的 xx ,接着在 13-16 行循环执行所有方法,如果有返回值则直接返回,到这里 before_request 的执行原理也就明了了。紧接着 flask.app.Flask.full_dispatch_request 中第 5 行接收到返回值,第 6、7 行判断如果返回值如果为空,才执行 self.dispatch_request 方法。而 self.dispatch_request 方法正是用来执行视图函数的。所以得出结论:如果 before_request 装饰器装饰的函数有返回值,那么将不会继续执行视图函数。
python框架之Flask(5)-@app.before_request原理的更多相关文章
- python框架之Flask(1)-Flask初使用
Flask是一个基于 Python 开发并且依赖 jinja2 模板和 Werkzeug WSGI 服务的一个微型框架,对于 Werkzeug 本质是 Socket 服务端,其用于接收 http 请求 ...
- python框架之Flask(4)-上下文管理
知识储备 偏函数 作用 偏函数,帮助开发者自动传递参数. 使用 import functools def index(a1, a2): return a1 + a2 # 原来的调用方式 # ret = ...
- python框架之Flask基础篇(二)-------- 数据库的操作
1.flask连接数据库的四步: 倒入第三方数据库扩展包:from flask_sqlalchemy import SQLAlchemy 配置config属性,连接数据库: app.config[&q ...
- python框架之Flask
介绍:Flask是一个使用 Python 编写的轻量级 Web 应用框架.其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2 . WSGl:Web Server Gateway ...
- python框架之Flask(3)-Blueprint(蓝图)
蓝图 用途 给开发者提供清晰的目录结构. 使用 目录结构 1.创建项目. 2.在项目目录下创建与项目名同名文件夹. 3.在 test_prj 文件夹下创建 __init__.py 文件,并在其中实例化 ...
- python框架之Flask基础篇(一)
一.第一个hello world程序 # coding=utf-8 from flask import Flask app = Flask(__name__) @app.route('/') def ...
- python框架之Flask基础篇(三)-------- 模版的操作
1.flask特有的变量和函数: 变量:g.session.request.config 函数:url_for().get_flashed_messages()这个函数注意了啊,记住这是个函数,别忘了 ...
- python框架之Flask(2)-路由和视图&Session
路由和视图 这一波主要是通过看源码加深对 Flask 中路由和视图的了解,可以先回顾一下装饰器的知识:[装饰器函数与进阶] 路由设置的两种方式 # 示例代码 from flask import Fla ...
- python框架之Flask(6)-flask-sqlalchemy&flask-script&flask-migrate使用
整合SQLAlchemy 安装 pip3 install flask-sqlalchemy 简单使用 from flask import Flask from flask_sqlalchemy imp ...
随机推荐
- [k8s]k8s内容索引
我会陆陆续续小结下. dns相关 dns策略 1.集群内 2.指定内网 subdomain 3.访问互联网 resovel.conf kube-dns架构图解及策略 nginx-ingress: DN ...
- python(61):str 和 bytes 转换
str 和 bytes 转换 b = b"example" # str object s = "example" # str to bytes bytes(s, ...
- python多线程应用——DB2数据库备份
前言:DB2一个实例下,可以存在多个数据库,之前使用shell备份脚本,但是同一时刻只能备份一个数据库,对于几百G的备份文件,这个速度显然太慢,今天学习了Python多线程,刚好应用一下. 分析:1. ...
- vue element-ui 的奇怪组件el-switch
https://segmentfault.com/q/1010000010008343
- vs 2015 项目筛选器没了,.h头文件和.cpp文件混在一起了
场景: git 拉取 VS 2015 项目,打开之后,.h头文件和.cpp文件混在一起了. 解决方案: 需要XXX..vcxproj.filters 文件.
- 网络I/O模型---同步异步阻塞非阻塞之惑
网络I/O模型 人多了,就会有问题.web刚出现的时候,光顾的人很少.近年来网络应用规模逐渐扩大,应用的架构也需要随之改变.C10k的问题,让工程师们需要思考服务的性能与应用的并发能力. 网络应用需要 ...
- C#项目”XXXXX”针对的是”.NETFramework,Version=v4.7.1”但此计算机没有安装它
遇到这样一个问题:C#项目”XXXXX”针对的是”.NETFramework,Version=v4.7.1”但此计算机没有安装它 就是我在打开别人的项目,发现别人的项目.Net Framework的版 ...
- 处理MySQL的ibdata1文件过大问题
ibdata1文件是什么? ibdata1是一个用来构建innodb系统表空间的文件,这个文件包含了innodb表的元数据.撤销记录.修改buffer和双写buffer.如果file-per-tabl ...
- makefile 常用函数
Linux下编译c/c++源码需要编写makefile文件,文章参看 http://blog.sina.com.cn/s/blog_4c4d6e74010009jr.html 一函数的调用语法 二字符 ...
- python数据分析及展示(三)
一.Pandas库入门 1. Pandas库的介绍 http://pandas.pydata.org Pandas是Python第三方库,提供高性能易用数据类型和分析工具 import pandas ...