4.3 详解flask上下文与出入栈

Flask工作原理

image.png

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?