Flask请求上下文执行流程(ctx)

flask项目一启动,有6个全局变量

_request_ctx_stack:LocalStack #LocalStack对象
_app_ctx_stack:LocalStack #LocalStack对象
current_app:LocalProxy(_find_app)
request:LocalProxy #LocalStack对象
session:LocalProxy #LocalStack对象
g:LocalProxy #LocalStack对象

 

请求来了

app.__call__()----->内部执行:self.wsgi_app(environ, start_response)

 

 

wsgi_app()

1.执行:ctx = self.request_context(environ):返回一个RequestContext对象,并且封装了request(当次请求的request对象),session。
2.执行:ctx.push():RequestContext对象的push方法
    2.1 push方法中中间位置382行有:_request_ctx_stack.push(self),self指的是ctx对象
    2.2 去_request_ctx_stack对象的类中找push方法(LocalStack中找push方法)
    2.3 push源码
def push(self, obj):
    # 通过反射找到self._local,在__init__实例化的时候生成的:self._local = Local()
    # Local() flask封装了支持线程和协程的local对象
    # 一开始取不到stack,返回None
    rv = getattr(self._local, "stack", None)
    if rv is None:

 

如果在视图函数中使用request对象,比如:print(request)

1.会调用request对象的`__str__`方法,request类是:LocalProxy
2.LocalProxy中的`__str__`方法:lambda x: str(x._get_current_object())
    1.内部执行_get_current_object()方法的源码如下:
    def _get_current_object(self):
        if not hasattr(self.__local, "__release_local__"):
        # self.__local()在__init__的时候,实例化的,在__init__中:object.__setattr__(self, "_LocalProxy__local", local)
        # 用了隐藏属性
        # self.__loacl
            # 实例化该类的时候传入的local(偏函数的内存地址:request = LocalProxy(partial(_lookup_req_object, "request")))
    3._lookup_req_object函数源码如下:
def _lookup_req_object(name):
    # name就是'request'字符串
    # top方法是把第二步中放入的ctx取出来,因为都在一个线程内,当前取到的就是当前请求的ctx对象
    top = _request_ctx_stack.top
    if top is None:
        raise RuntimeError(_request_ctx_err_msg)
    4.所以:print(request)实质上是在打印当次请求的request对象的__str__

 

如果在视图函数中使用request对象

比如:print(request.method):实质上是取到当次请求的request对象的methid属性

 

最终,请求结束执行

ctx.auto_pop(error)# 把ctx移除掉

 

 

posted @ 2019-08-05 09:43  -Rye-  阅读(481)  评论(0)    收藏  举报