Flask之上下文管理源码分析1

13 篇文章 0 订阅

对整个上下文管理过程做描述
并对请求到来处理阶段做了详细描述

1. 源码分析

可以根据源码的内容,分析一次请求从到来到结束,源码中到底做了哪些操作

# 1.app开始运行
app运行前,会先执行其__call__方法,进而执行wsgi_app方法
	- self.wsgi_app(environ, start_response)

# 2.打包
ctx = self.request_context(environ)
    - ctx.request = request_class(environ) = request
    - ctx.session = None # 第一次请求session会为空


# 3.将打包好的内容,放到Local对象中
ctx.push()	# 分为AC和RC的push两个动作
    # 1)app的push操作
    - app_ctx = self.app.app_context()  # app_ctx = AppContext(app,g)
    - app_ctx.push()    # app_ctx = LocalStack()    同理,LocalStack中也有一个Local
        - AppContext
            - __init__
            - self.app = app    # 封装了一个app,app即当前实例化Flask的对象
            - self.g = app.app_ctx_global_class()   # 封装了一个g,g可以看作一次请求中的全局变量
	# 也就是说,通过_app_ctx_stack(LocalStack)将app_ctx放置到Local对象中

    # 2)request的push操作
    - _request_ctx_stack.push(self) # 具体放的动作
        - _request_ctx_stack = LocalStack() #
        - self._local = Local()
        - self._local.stack = rv = []   # rv = getattr(self._local, "stack", None) 当rv=None时,放置一个空的列表进去
            - storage[ident][name] = value # 执行_local的__setattr__方法
    # 也就是说,通过_request_ctx_stack(LocalStack)将ctx放置到Local对象中
    数据:
        {
            请求1:{"stack":[ctx(request,session),]},
            请求2:{"stack":[ctx(request,session),]}, # 此时session还为空
            ...请求n号...
        }
    - self.session = session_interface.open_session(self.app, self.request) # 打开ctx中的session,并为session赋值
    # - 路由匹配 会执行self.match_request(),了解即可

# 4.找视图函数
response = self.full_dispatch_request()
    - rv = self.preprocess_request() # preprocess_request,解决执行视图函数之前的一些事宜,即执行before_request
    - rv = self.dispatch_request()  # 执行视图函数
    - self.finalize_request(rv) # 执行after_request 和 save_session
        - response = self.process_response(response)
            - funcs = chain(funcs, reversed(self.after_request_funcs[bp]))  # 执行after_request的操作
            - self.session_interface.save_session(self, ctx.session, response)  # 执行save_session,把现有的值拿来保存到浏览器cookie中


# 5.pop操作
ctx.auto_pop(error)
    - self.pop(exc)
        - rv = _request_ctx_stack.pop() 执行pop操作,将上述push到栈中的数据pop掉
        数据:
            {
                请求1:{"stack":[ctx(request,session),]},
                请求2:{"stack":[ctx(request,session),]}, # pop掉
                ...请求n号...
            }
    - app_ctx.pop(exc)	# 同理
            {
                请求1:{"stack":[app_ctx(app,g),]},
                请求2:{"stack":[app_ctx(app,g),]},, # pop掉
                ...请求n号...
            }

上述的源码基本都在app.pyctx.py两个Flaks源码文件中

2. 总结步骤

根据以上源码中的动作,我们大概能把上下文机制分为三个阶段,其中每个阶段又有自己要做的工作,具体如下

# 第一阶段,请求到来处理阶段
    # 打包请求数据到ctx(ctx = self.request_context(environ))
    # 将ctx(request,session)放到Local对象(ctx.push)

# 第二阶段:视图调用实现具体业务阶段
    # 视图函数导入 request/session,执行一系列视图函数定义的操作(self.full_dispatch_request())

# 第三阶段:处理结束返回阶段
    # 请求处理完毕,获取session并保存到cookie(save_session操作);
    # 并将ctx删除(pop操作)

3. 补充

3.1 Flask中的session是什么时候创建的,又是什么时候销毁的?

  1. 当请求刚进来时,会将request和session封装成一个RequestContext对象,然后通过LocalStack将ctx放入到一个Local对象中;
  2. 执行open_session操作,读取cookie中的值,拿出来重新赋值到Local对象中的ctx中
  3. 当返回结果时,执行save_session,将ctx中的session读出,并序列化,然后写入到Cookie中(给用户了),然后返回response
  4. 执行pop,将ctx从Local中移除

3.2 扩展AC部分

上述的分析,未对视图处理部分做详细描述,下篇博客中会进行补充

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值