zoukankan      html  css  js  c++  java
  • Flask上下文管理源码分析

    上下文管理本质(类似于threading.local):

      1.每一个线程都会在Local类中创建一条数据:

    {
      "唯一标识":{stark:[ctx,]},
      "唯一标识":{stark:[ctx,]},    
    }

      2.当请求进来之后,将请求相关数据添加到列表里面[request,],以后如果使用时,就去读取。

      3.列表中的数据,请求完成之后,将request从列表中移除,

    在源码中分析上下文管理:

      1,存数据,2,执行视图函数,3,请求结束。

      第一阶段:执行__call__--->app.wsgi-->将ctx(request,session)封装为RequestContext()在(open_session),app_ctx(g,app)封装为APPContent()通过LocalStack将这两个类放入Local对象中。

    # 在封装到RequestContext()时,
    # request = Request对象
    # session = None
    
    # 在执行ctx.push()时,才给session赋予了值。
    
    # ctx.session = self.session_interface.open_session(self,request)

      第二阶段:视图函数导入:request/session/g/app,通过偏函数(_lookup_req_object)在通过(LocalProxy())去LocalStack中的Local类中对其进行增删改查操作。

    # 执行视图函数
    
    # response = self.full_dispathch_request()  读取ctx.session将数据写入到浏览器的cookie中。
    
    # 执行偏函数
    
    # request = LocalProxy(partial(_lookup_req_object,"reqeust"))
    # _local = 偏函数
    # __getattr__
    #    ctx.request.method    ( top, pop ....)
    
    #    ctx.request.args
    
    
    # session 也在此时写入数据
    
    # session = LocalProxy(partial(_look_req_object,"session"))
    
    # _local = 偏函数
    # __setitem__
    #     ctx.session["xx"] == 123

      第三阶段:请求处理完毕:

        通过save_session将签名session保存到cookie.

        通过ctx.pop()去LocalStack中的Local类中将ctx删除。

    有关面试问题:

    flask和django的区别:
        对于django来说,内部组件特别多,自身功能强大,大而全,。
        flask内置组件很少,但是第三方组件很多,扩展性强。
        因为他们两个框架都没有写socket,都是基于wsgi协议做的,除此之外,flask框架中的上下文管理较为耀眼。
        相同点:都没有socket,都是基于wsig协议做的。
        不同点:
            请求相关的数据传递的方式不同:
                django:通过传递request参数取值。
                f'lask:
            组件不同:
                django:大而全。
                flask:第三方组件多。

    flask上下文管理:

      简单来说,flask上下文管理可以分为三个阶段:

        1,请求进来时,将请求相关的数据放入上下文管理中。

        2,在视图函数中,要去上下文管理中取值。

        3,请求响应,要将上下文管理中的数据清除。

      详细点来说:

        1,请求刚进来,将request,session封装在RequestContext类中,app,g封装在AppContext类中,并通过LocalStack将reqeustcontext和appcontext放入Local类中。

        2,视图函数中,通过LocalProxy-->偏函数-->LocalStack-->Local取值。

        3,请求响应时,先执行save.session()再各自执行pop(),将Local中的数据清除。

    Flask中的session是什么时候创建,什么时候销毁:

      当请求进来时,会将request和session封装为一个RequestContext对象。通过LocalStack将RequestContex放入到Local对象中,因为请求第一次进来的时候,session是空值,所以执行open_session,给session赋值,再通过视图函数处理,请求响应时执行save.session,将签名session写入到用户浏览器的cookie中,再将Local中的数值pop掉。

    Flask中一共有几个LocalStack和Local对象。

      有两个LocalStack,两个Local。

      request和session共用一个LocalStack和Local。

      g和 app 共用一个LocalStack 和 Local.

    为什么把请求放到RequestContext中:

      因为request和session都是在视图中操作频繁的数据,也是用户请求需要用的数据。将request和session封装在RequestContext中,使用top,pop方法,一次就可以完成。如果单独封装,就会操作频繁。

    ctx = RequestContext(request,session)

    Local的作用:

      保存数据,请求上下文对象和app上下文对象。

    LocalStack的作用:

      将Local对象中的数据维护成一个栈 [ctx,ctx,....](先进后出)

      { "协程或线程的唯一标识":{stack: [ ctx,ctx,... ] } }

    为什么要维护成一个栈:

      当时web应用时:不过是单线程还是多线程,栈中只有一个数据。

        服务端单线程:{111:{stack:[ ctx, ] }

        服务端多线程:{111:{stack:[ ctx, ] },112:{stack: [ctx, ] }}

        离线脚本:可以在栈中放入多个数据:

          with app01.app_context():

            print(current_app)

            with app02.app_context():

              print(current_app)

            print(current_app)

    什么是 g:

      g 相当于一次请求的全局变量,当请求进来时将g和current_app封装为一个APPContext类,再通过LocalStack将AppContext放入到Local类中,取值时t通过偏函数,LocalStack,Local中取值,响应时将Local中的数据g删除。

    上下文管理的技术点:

      反射:LocalProxy()

      面向对象,封装:RequestContext

      线程。

  • 相关阅读:
    浅谈Cauchy不等式
    终于结束的起点——CSP-S 2019 第二轮游记
    LOJ 10172 涂抹果酱
    数字表格
    CSP-S 2019 第一轮 游记
    20191011模拟赛
    Luogu 2327 扫雷
    NOIAC 30 candy
    FormData文件上传
    sde表空间无法导入数据和编辑
  • 原文地址:https://www.cnblogs.com/stfei/p/9910528.html
Copyright © 2011-2022 走看看