4.3 详解flask上下文与出入栈
Flask工作原理

1.当一个请求进入Flask框架,首先会实例化一个Request Context,这个上下文封装了请求的信息在Request中,并将这个上下文推入到一个栈(_request_ctx_stack/_app_ctx_strack)的结构中,即之前将的push方法
2.RequestContext在入_request_ctx_stack之前,首先会检查_app_ctx_strack是否为空,如果为空,则会把一个AppContext的对象入栈,然后再将这个请求入栈到_request_ctx_stack中
3.我们的current_app和request对象都是永远指向_app_ctx_strack/_request_ctx_stack的栈顶元素,也就是分别指向了两个上下文,如果这两个值是空的,那么LocalProxy就会出现unbound的状态
4.当请求结束的时候,这个请求会出栈-pop
回到我们之前的测试代码,如果要想让我们的测试代码正常运行,就需要手动将一个AppContext入栈。
from flask import Flask, current_app
app = Flask(__name__)
# 获取AppContext,里面的代码很简单,就是:return AppContext(self)
ctx = app.app_context()
# 将AppContext入栈
ctx.push()
# 断点调试这里显示current_app=[LocalProxy]<LocalProxy unbound>
a = current_app
# RuntimeError: Working outside of application context.
b = current_app.config["DEBUG"]
print(b)
注意
虽然current_app和request指向的是两个上下文,但是他们返回的却是Flask核心独享和Request对象。下面来看下这部分的源码
globals.py
# globals.py中实例化LocalProxy获取current_app的代码中,传入了一个_find_app方法
current_app = LocalProxy(_find_app)
def _find_app():
# 取栈顶元素
top = _app_ctx_stack.top
if top is None:
raise RuntimeError(_app_ctx_err_msg)
# 获取ctx中的app对象
return top.app
从源码中可以看到,他获取的是app核心对象。
Last updated
Was this helpful?