成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

深入理解flask框架(2):應(yīng)用上下文與請(qǐng)求上下文

wushuiyong / 1206人閱讀

摘要:實(shí)現(xiàn)一個(gè)進(jìn)程中擁有多個(gè)應(yīng)用上下文機(jī)制依賴的數(shù)據(jù)結(jié)構(gòu)上下文機(jī)制的實(shí)現(xiàn)基于的。

什么是上下文?

flask框架中的上下文本質(zhì)上就是兩個(gè)類,我們可以先看一下他的初始化函數(shù):
應(yīng)用上下文

class AppContext(object):
    """The application context binds an application object implicitly
    to the current thread or greenlet, similar to how the
    :class:`RequestContext` binds request information.  The application
    context is also implicitly created if a request context is created
    but the application is not on top of the individual application
    context.
    """

    def __init__(self, app):
        self.app = app
        self.url_adapter = app.create_url_adapter(None)
        self.g = app.app_ctx_globals_class()

        # Like request context, app contexts can be pushed multiple times
        # but there a basic "refcount" is enough to track them.
        self._refcnt = 0

請(qǐng)求上下文

class RequestContext(object):
    def __init__(self, app, environ, request=None):
        self.app = app
        if request is None:
            request = app.request_class(environ)
        self.request = request
        self.url_adapter = app.create_url_adapter(self.request)
        self.flashes = None
        self.session = None
        self._implicit_app_ctx_stack = []
        self.preserved = False
        self._preserved_exc = None
        self._after_request_functions = []
        self.match_request()
為什么設(shè)計(jì)上下文這樣的機(jī)制?

詳細(xì)解釋可參考:
https://blog.tonyseek.com/pos...

多線程環(huán)境下,實(shí)現(xiàn)線程之間的隔離

類似Thread Local ,每個(gè)線程對(duì)一個(gè) Thread Local 對(duì)象的修改都不會(huì)影響其他線程。這種對(duì)象的實(shí)現(xiàn)原理也非常簡(jiǎn)單,只要以線程的 ID 來保存多份狀態(tài)字典即可,就像按照門牌號(hào)隔開的一格一格的信箱。

實(shí)現(xiàn)一個(gè) Python 進(jìn)程中擁有多個(gè)應(yīng)用

from werkzeug.wsgi import DispatcherMiddleware
from biubiu.app import create_app
from biubiu.admin.app import create_app as create_admin_app

application = DispatcherMiddleware(create_app(), {
    "/admin": create_admin_app()
})
上下文機(jī)制依賴的數(shù)據(jù)結(jié)構(gòu)

flask上下文機(jī)制的實(shí)現(xiàn)基于 Werkzeug 的 Local Stack 。
閱讀源碼,Local Stack又依賴于local類,我們發(fā)現(xiàn)Local類的本質(zhì)是一個(gè)字典和一個(gè)獲取到線程id的函數(shù)。

class Local(object):
    __slots__ = ("__storage__", "__ident_func__")

    def __init__(self):
        object.__setattr__(self, "__storage__", {})
        object.__setattr__(self, "__ident_func__", get_ident)

而LocalStack在Local類的基礎(chǔ)上又實(shí)現(xiàn)了棧的功能。

class LocalStack(object):
        def __init__(self):
        self._local = Local()

flask中應(yīng)用上下文棧和請(qǐng)求上下文棧正是基于上面的LocalStack類

_request_ctx_stack = LocalStack()
_app_ctx_stack = LocalStack()

下面我們通過一些實(shí)驗(yàn)來進(jìn)一步學(xué)習(xí)flask的執(zhí)行過程:

In [1]:  from flask.globals import _app_ctx_stack, _request_ctx_stack

In [2]: from flask import Flask

In [3]: app = Flask(__name__)

In [4]: _app_ctx_stack._local.__storage__
Out[4]: {}

In [5]: _request_ctx_stack._local.__storage__
Out[5]: {}

In [6]: req_ctx = app.test_request_context()

In [7]: req_ctx.push()

In [8]: _request_ctx_stack._local.__storage__
Out[8]: {: {"stack": []}}

In [9]: _app_ctx_stack._local.__storage__
Out[9]: {: {"stack": []}}

我們可以看到一開始上下文均為空,test_request_context()函數(shù)會(huì)生成一個(gè)請(qǐng)求上下文,我們通過push讓它入棧,之后兩個(gè)上下文都有了內(nèi)容,為什么_app_ctx_stack中也有內(nèi)容呢?
我們可以看一下源碼,第一次請(qǐng)求上下文push時(shí),app_ctx如果為None,就會(huì)調(diào)用_implicit_app_ctx_stack_添加一個(gè)應(yīng)用上下文。

        app_ctx = _app_ctx_stack.top
        if app_ctx is None or app_ctx.app != self.app:
            app_ctx = self.app.app_context()
            app_ctx.push()
            self._implicit_app_ctx_stack.append(app_ctx)
        else:
            self._implicit_app_ctx_stack.append(None)

這里我們就可以解釋flask中wsgi_app這部分代碼,每次web服務(wù)器為flask提供了http請(qǐng)求的environ變量,flask就會(huì)創(chuàng)建一個(gè)request_context對(duì)象,執(zhí)行push()
之后上下文對(duì)象就會(huì)進(jìn)入_request_ctx_stack中,并在執(zhí)行處理函數(shù)之后會(huì)自動(dòng)pop,
所以我們說請(qǐng)求上下文的生命周期就是一次請(qǐng)求的過程。

   def wsgi_app(self, environ, start_response):
        ctx = self.request_context(environ)
        error = None
        try:
            try:
                ctx.push()
                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)

整體流程可參考:
https://www.jianshu.com/p/2a2...

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/41133.html

相關(guān)文章

  • 從零開始搭建論壇(三):Flask框架簡(jiǎn)單介紹

    摘要:我們的論壇項(xiàng)目就使用了該框架。此外,麥子學(xué)院也有一個(gè)入門視頻教程,一共小時(shí)的視頻教程,涵蓋開發(fā)的方方面面,包括環(huán)境的搭建,語法介紹,項(xiàng)目結(jié)構(gòu)的組織,全球化,單元測(cè)試等內(nèi)容。博客地址更多閱讀的機(jī)制三個(gè)框架的對(duì)比 前面兩篇文章中我們已經(jīng)了解 Web(HTTP)服務(wù)器,Web應(yīng)用程序,Web框架,WSGI這些 Python Web 開發(fā)中的概念。我們知道,Web框架通過將不同Web應(yīng)用程序中...

    Alan 評(píng)論0 收藏0
  • 深入理解flask框架(3):configextension

    摘要:中的配置,都是通過來控制那么究竟是什么再來看函數(shù)而是什么再轉(zhuǎn)向看的源碼,可以看到類繼承于字典也就是說的就是一個(gè)特殊的字典,用于保存配置項(xiàng)。 config flask中的配置,都是通過config來控制那么config究竟是什么? self.config = self.make_config(instance_relative_config) 再來看make_config函數(shù): def ...

    wmui 評(píng)論0 收藏0
  • 深入 Flask 源碼理解 Context

    摘要:主要的作用是將維護(hù)的字典中鍵為對(duì)應(yīng)的值定義為。如果沒有,則會(huì)將當(dāng)前到中,同時(shí)將加入列表中否則添加。注意清理之后的動(dòng)作。上述代碼涉及到,它強(qiáng)調(diào)必須是一個(gè)可調(diào)用對(duì)象。后期的工作之一是了解。這僅僅是我的個(gè)人理解。實(shí)際上這是解決多個(gè)實(shí)例運(yùn)行的問題。 Flask 中的上下文對(duì)象 知乎問題 編程中什么是「Context(上下文)」 已經(jīng)能夠簡(jiǎn)單地說明什么是 Context,它是一個(gè)程序需要的外部對(duì)...

    ninefive 評(píng)論0 收藏0
  • flask源碼走讀

    摘要:另外,如果你對(duì)模板渲染部分的內(nèi)容感興趣,也可以考慮閱讀文檔文檔文檔源碼閱讀,可以參考下面的函數(shù)打斷點(diǎn),再測(cè)試一個(gè)請(qǐng)求,理清過程。 Flask-Origin 源碼版本 一直想好好理一下flask的實(shí)現(xiàn),這個(gè)項(xiàng)目有Flask 0.1版本源碼并加了注解,挺清晰明了的,我在其基礎(chǔ)上完成了對(duì)Werkzeug的理解部分,大家如果想深入學(xué)習(xí)的話,可以參考werkzeug_flow.md. 閱讀前 為...

    Coly 評(píng)論0 收藏0
  • 深入理解flask框架(4):session

    摘要:中的實(shí)現(xiàn)是基于。打開源碼的文件,我們可以看到最后的接口類中,主要有兩個(gè)函數(shù)。這個(gè)系列就此完結(jié)。 flask中session的實(shí)現(xiàn)是基于cookie。打開flask源碼的session.py文件,我們可以看到最后的接口類中,主要有open_session,save_session兩個(gè)函數(shù)。 class SecureCookieSessionInterface(SessionInterfa...

    PingCAP 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<