当我们运行项目后,Flask内部都经历了什么
1、app.run()启动项目,ctrl点进源码
app.py:
1)执行了run_simple()
2)注意第三个参数,这里是Flask实例化的对象,在这里会执行Flask的__call__()方法:
3)调用wsgi_app()方法,再调用requet_context():
4)实例化了一个RequestContext对象
ctx.py:
5)RequestContext初始化时,1处调用 app.create_url_adapter 方法,把 app 的 url_map 绑定到 WSGI environ 变量上。
6)之后在__init__里又调用了match_request()
7)这个方法调用了 url_adapter.match 方法,进行实际的匹配工作,返回匹配的 url_rule。
8)回到4那里,我们知道了requet_context()返回的就是create_url_adapter 处理后的environ变量,并封装到RequestContext里,接下来,创建请求上下文,并调用了app.push()方法把它压栈:
,这里调用了_request_ctx_stack的push方法,而_request_ctx_stack是:
9)_request_ctx_stack是LocalStack类的对象,在实例初始化时,又实例化了一个Local()对象
10)Local对象初始化时,设置了__storage__和__ident_func__两个属性,这两个属性前者是存储封装后的request请求的,后者是给该请求添加唯一标识的。
11)回到8,_request_ctx_stack.push(self)就是调用了LocalStack里的push方法,并将RequestContext的实例对象传了过去,然后添加进了一个空列表
到此,app.push()的操作已完成
12)继续往后看,调用了full_dispatch_request():
13)这个函数是处理请求的开始地方,最核心的内容是 dispatch_request
,加上处理请求的 hooks 和错误处理的内容。self.dispatch_request()
返回的是处理函数的返回结果(比如 hello world 例子中返回的字符串),finalize_request
会把它转换成 Response
对象。
14)在 dispatch_request
之前我们看到 preprocess_request
,之后看到 finalize_request
,它们里面包括了请求处理之前和处理之后的很多 hooks 。这些 hooks 包括:
- 第一次请求处理之前的 hook 函数,通过
before_first_request
定义,执行过程如下
调用了self.try_trigger_before_first_request_functions()
- 每个请求处理之前的 hook 函数,通过
before_request
定义
调用了preprocess_request(),其中bp是使用蓝图后做的处理,暂不考虑使用蓝图的情况。
- 每个请求正常处理之后的 hook 函数,通过
after_request
定义
调用finalize_request(rv):
调用了process_response(response),ctx是app.push()添加进去的请求对象的最后一个:
- 不管请求是否异常都要执行的
teardown_request
hook 函数,它是在整个请求完成,最后pop的过程中被执行的
dispatch_request
要做的就是找到我们的处理函数,并返回调用的结果,也就是路由的过程。