Flask源码流程剖析

Posted Fugui

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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)

 

以上是关于Flask源码流程剖析的主要内容,如果未能解决你的问题,请参考以下文章

01 flask源码剖析之werkzurg 了解wsgi

flask 上下文管理 &源码剖析

flask 启动函数返回值的剖析

Flask 源码剖析请求入口

Python微框架Flask源码剖析

剖析Flask上下文管理(源码)