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

Posted liuxiangpy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剖析Flask上下文管理(源码)相关的知识,希望对你有一定的参考价值。

一、源码开始

示例一

from  flask import  Flask


#1. 实例化Flask对象
app = Flask(__name__)


#2. 设置路由
"""
app.url_map = [ 
        (‘/login‘, login)
        (‘/home‘, home)
    ]
"""

@app.route(/index)
def index():
    return index



if __name__ == __main__:
    #3. 启动socket服务端
    app.run()

在以上示例中,app.run是请求的入口,而app是Flask实例化的对象,所以执行的是Flask类中的run方法,而在该改方法中又执行了run_simple方法,以下是run方法部分源码摘抄(其中self就是app对象):

from werkzeug.serving import run_simple

try:
    run_simple(host, port, self, **options)
finally:
    # reset the first request information if the development server
    # reset normally.  This makes it possible to restart the server
    # without reloader and that stuff from an interactive shell.
    self._got_first_request = False

在run_simple中会执行app(environ, start_response),参考werkzeug的源码,源码会执行app(environ, start_response)也就是执行app的__call__方法,以下是__call__方法源码摘抄:

1. 当用户请求来以后会执行__call__方法, __call__方法返回值是执行wsgi_app.

def __call__(self, environ, start_response):
    """The WSGI server calls the Flask application object as the
    WSGI application. This calls :meth:`wsgi_app` which can be
    wrapped to applying middleware."""
    return self.wsgi_app(environ, start_response)  #当用户请求进来后会执行wsgi_app将请求的数据和响应的数据传到wsgi_app中

2.执行wsgi_app

    def wsgi_app(self, environ, start_response):
        """The actual WSGI application. This is not implemented in
        :meth:`__call__` so that middlewares can be applied without
        losing a reference to the app object. Instead of doing this::

            app = MyMiddleware(app)

        It‘s a better idea to do this instead::

            app.wsgi_app = MyMiddleware(app.wsgi_app)

        Then you still have the original application object around and
        can continue to call methods on it.

        .. versionchanged:: 0.7
            Teardown events for the request and app contexts are called
            even if an unhandled error occurs. Other events may not be
            called depending on when an error occurs during dispatch.
            See :ref:`callbacks-and-errors`.

        :param environ: A WSGI environment.
        :param start_response: A callable accepting a status code,
            a list of headers, and an optional exception context to
            start the response.
        """

        """
        1. 获取environ并对其进行再次封装
        2. 从environ中获取名称为session的cookie,解密,反序列化。
        3. 放在一个存数据的地方
        """
        # ctx = RequestContext(self,environ) #self就是app对象,environ请求相关原始的数据
        # ctx.request = app.request_class(environ)
        ctx = self.request_context(environ)
        error = None
        try:
            try:
                #将ctx放到一个存放数据的地方
                #执行SecureCookieSessionInterface.open_session,去cookie中获取值并给ctx.session重新赋值
                ctx.push()
                #4.执行视图函数
                #5.“获取某个地方的session”加密 => 写cookie
                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
            ctx.auto_pop(error)

            """
            6、“某个神奇的”位置清空
            """

 

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

flask源码剖析之LocalStack和Local对象实现栈的管理

深度剖析Flask上下文管理机制

flask上下文管理相关 - threading.local 以及原理剖析

Flask上下文管理源码分析

源码解读:Flask 上下文核心机制

11.6 Flask 源码流程,上下文管理