• Flask源码流程剖析


    在此之前需要先知道类和方法,个人总结如下:

     1.对象是类创建,创建对象时候类的__init__方法自动执行,对象()执行类的 __call__ 方法
     2.类是type创建,创建类时候type的__init__方法自动执行,类() 执行type的 __call__方法(类的__new__方法,类的__init__方法)

    # 第0步: 执行type的 __init__ 方法【类是type的对象】
    class Foo:
        def __init__(self):
            pass

        def __call__(self, *args, **kwargs):
            pass

     第1步: 执行type的 __call__ 方法
           1.1  调用 Foo类(是type的对象)的 __new__方法,用于创建对象。
           1.2  调用 Foo类(是type的对象)的 __init__方法,用于对对象初始化。
    obj = Foo()
    # 第2步:执行Foodef __call__ 方法
    obj()

    再来我们以下面例子作为参考

    from flask import Flask
    
    app = Flask(__name__)
    
    
    @app.route('/')
    def hello_world():
        return 'Hello World!'
    
    
    if __name__ == '__main__':
        app.run()

    1,首先执行Flask类的__call__方法:

    class RequestContext(object):
        def __init__(self,environ):
            self.environ = environ
    
        def push(self):
            # 3
            # 请求相关数据,加到local中: stack.push...
            _request_ctx_stack.push(self)
    
            # 获取cookie中的随机字符串,检验是否有,没有就生成
            # 根据随机字符串,获取服务端保存的session的
            # {
            #     'xxxxxxx': {...}
            #     'xxxxxxx': {...}
            # }
            # 新用户: {}
            # 老用户:{user:'xxx'}
            self.session = self.app.open_session(self.request)
            if self.session is None:
                self.session = self.app.make_null_session()
    
    
    class Flask:
        def process_response(self, response):
            # 8
            # 执行 after_request装饰器
            for handler in funcs:
                response = handler(response)
    
            # 将内存中的session持久化到:数据库、....
            if not self.session_interface.is_null_session(ctx.session):
                self.save_session(ctx.session, response)
    
            return response
    
        def finalize_request(self, rv, from_error_handler=False):
            # 7
            response = self.make_response(rv)
            try:
                response = self.process_response(response)
                request_finished.send(self, response=response)
            except Exception:
                if not from_error_handler:
                    raise
                self.logger.exception('Request finalizing failed with an '
                                      'error while handling an error')
            return response
    
        def full_dispatch_request(self):
            # 5
    
            # 触发只执行一次的装饰器函数,@before_first_request
            self.try_trigger_before_first_request_functions()
            try:
                # 触发Flask的信号,没用: pip3 install blinker
                request_started.send(self)
    
                # 执行特殊装饰器:before_request
                # 如果没有返回值,rv=None;有返回值 “嘻嘻嘻”
                rv = self.preprocess_request()
                if rv is None:
                    # 触发执行视图函数
                    rv = self.dispatch_request()
            except Exception as e:
                rv = self.handle_user_exception(e)
    
            # 6 对返回值进行封装
            return self.finalize_request(rv)
    
        def wsgi_app(self, environ, start_response):
    
            # 处理request,将请求添加到local中
            ctx = self.request_context(environ)
            # 2.处理request和session
            ctx.push()
    
            error = None
            try:
                try:
                    # 4 执行视图函数
                    response = self.full_dispatch_request()
                except Exception as e:
                    error = e
                    response = self.handle_exception(e)
                except:
                    error = sys.exc_info()[1]
                    raise
                return response(environ, start_response)
            finally:
                if self.should_ignore_error(error):
                    error = None
                # 9
                ctx.auto_pop(error)
    
        def __call__(self, environ, start_response):
            """Shortcut for :attr:`wsgi_app`."""
            return self.wsgi_app(environ, start_response) 

    1,执行Flask的__call__方法

    2,wsgi_app(request_context(environ),push) 对request和session的处理,第一次进来session为None,进行push

    3,请求相关数据,加到local中: stack.push。获取cookie中的随机字符串,检验是否有,没有就生成根据随机字符串,获取服务端保存的session的

    4,执行视图函数    full_dispatch_request()

    5,触发只执行一次的装饰器函数,@before_first_request  > ( 触发Flask的信号,没用: pip3 install blinker) >  执行特殊装饰器:before_request 如果没有返回值,rv=None;有返回值 ,rv="  返回值  "

    6 ,  对返回值进行封装    return self.finalize_request(rv)

    7 ,  对封装的数据进行处理,并返回 response

    8 , 执行 process_response(self, response):     执行 after_request装饰器   将内存中的session持久化到:数据库、redis、 ....

    9 , 最后返回数据,并进行  ctx.auto_pop(error)

  • 相关阅读:
    VS Code 中文显示乱码_ubuntu
    解决source insight不识别.cu文件的问题/sourceinsight设置.cu类型的文件
    PPT图片素材
    Jetson Xavier NX apt更换国内源
    xavier NX安装torchvision
    xavier NX上安装pytorch_前面一二三四是失败的方法,可以直接按照步骤五进行安装
    jquery.cookie()方法
    JavaScript错误处理
    Jquery中$.post()与$.get()区别
    jQuery中$.get()、$.post()和$.ajax()
  • 原文地址:https://www.cnblogs.com/yifugui/p/8244508.html
Copyright © 2020-2023  润新知