1. 程式人生 > >剖析Flask上下文管理(源碼)

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

ear 其中 log turn 神奇 from callable actual war

一、源碼開始

示例一

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上下文管理(源碼)