• flask源码分析


    通过查看源码,我们知道app.run() 方法其实是执行了run_simple() 方法,源码如下:

          

      我们可以通过下面一段代码探究run_simple() 方法都做了什么?

    复制代码
      from werkzeug.serving import run_simple
      from werkzeug.wrappers import Request, Response
    
      @Request.application
      def app(req):
        print(req.method)    # GET
        print(req.path)     # /
        return Response('200 ok')
    
      run_simple('0.0.0.0', 5000, app)
    复制代码

      运行代码,发现服务运行在http://0.0.0.0:5000/上,如下:

          

      浏览器访问该网址控制台显示的网址,输出结果如上图,且页面显示返回结果'200 ok'。由此说明视图函数app执行了,再看我们之前写的代码:

    复制代码
      from flask import Flask, ...
    
      app = Flask(__name__)
    
      ......
      
      app.run(debug=True)         # app 是flask的实例化对象
    复制代码

      这里重点分析app.run() 都干了什么?

      首先,执行app.run() 时,源码中显示执行了执行run_simple() 方法,源码中run_simple() 方法的参数是run_simple(host, port, self, **options) ,这里重点看第三个参数self,因为app是flask的实例化对象,因此self就是指flask的实例化对象app,而上例中我们知道当有请求进来的时候,执行了app(),我们知道函数加括号是执行,而对象加括号会自动执行__call__方法,也就是说app.run() 其实是监听了flask类中的__call__方法,通过解读源码我们发现__call__方法内容如下:

          

      __call__方法中执行了wsgi_app方法,源码如下:

         

      request_context() 方法源码如下,其中的self仍然是Flask的实例化对象app:

         

      RequestContext是一个类,它的__init__方法源码如下:

         

      接下来我们重点分析flask是如何做到把request对象当成全局变量,而又保证了数据安全,即请求信息互不影响的。

      1、flask请求上文源码解读  

      上篇我们分析到了如何得到RequestContext实例化对象ctx,接下来ctx对象执行push方法,如下:

        

      RequestContext类中的push方法源码如下:

        

      _request_ctx_stack是LocalStack类的实例化对象:

         

      LocalStack类中的__init__方法如下:

        

      Local类的__init__方法如下:

        

      get_ident是Local类所在文件中导入的一个方法名,该方法执行后会得到线程或协程ID,如下:

        

      LocalStack类中的top是一个属性方法,源码如下:

        

      下一步Local类中的__getattr__方法源码如下:

        

      到此,分析得出top = _request_ctx_stack.top中的top为None。

      接下来分析 _request_ctx_stack.push(self)做了什么?LocalStack类中的push方法源码如下:

        

      Local类中的__setattr__方法源码如下:

        

      因为rv.append(obj),所以最后LocalStack对象,即_request_ctx_stack对象字典化后如下:

      {'_local':{'__storage__':{9527:{stack:[ctx]}}, '__ident_func__':get_ident}}
      # 说明:9527假设是获取到的线程或者协程号,ctx包含request对象和session对象。

      到此,flask请求上文结束,也就是完成了将一个request和session对象存储到某个地方。

      2、下文  

      我们知道flask的request对象和session对象是全局变量,上文已经解读了如何存储。接下来解读如何在保证数据安全的情况下取出来,即只取到自己的请求信息而非其他人的。

      我们还知道request对象中存储了很多信息,如request.method存储请求方式、request.json存储json标准字符串等等。下面以request.method为例,分析如何得到请求方式信息。

      导入request方式如下:

      from flask import request

      源码如下:

        

      LocalProxy类的__init__方法如下:

        

      偏函数中的原函数_lookup_req_object源码如下:

        

      当执行request.method的时候,执行LocalProxy的__getattr__方法,源码如下:

        

      查看类LocalProxy中的_get_current_object方法是如何得到本次请求的request对象,源码如下:

        

      至此,我们已经分析出了如何得到本次请求的request对象,从而取出request对象中的相关信息。

  • 相关阅读:
    10分钟教你用Python玩转微信之抓取好友个性签名制作词云
    1. 配置win7下odbc数据源找不到数据库驱动的问题
    1. 加签和会签的区别
    4. mysql 1449 : The user specified as a definer ('test'@'%') does not exist 解决方法
    1. 在config.ini文件中加入dm.park.time=1,会使uap中的tomcat启动加快
    37. sqlplus工具连接服务端或其他电脑的oracle方式
    36. Oracle查询数据库中所有表的记录数
    4. mysql 查看数据库中所有表的记录数
    35. Oracle监听器启动出错:本地计算机上的OracleOraDb11g_home1TNSListener服务启动后又停止了解决方案
    4. powerdesigner 生成sql脚本步骤
  • 原文地址:https://www.cnblogs.com/miaoweiye/p/12581565.html
Copyright © 2020-2023  润新知