国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

深入理解flask框架(1):WSGI與路由

xiaolinbang / 461人閱讀

摘要:是一個小而美的微框架,主要依賴于和,只建立和的橋梁,前者實現(xiàn)一個合適的應(yīng)用,后者處理模板。本文主要分析了是在基礎(chǔ)上如何構(gòu)建接口與路由系統(tǒng)的。網(wǎng)關(guān)協(xié)議的本質(zhì)是為了解耦,實現(xiàn)服務(wù)器和應(yīng)用程序的分離,就是一個支持的服務(wù)器與應(yīng)用程序之間的約定。

flask是一個小而美的微框架,主要依賴于Werkezug 和 Jinja2, Flask 只建立 Werkezug 和 Jinja2 的橋梁,前者實現(xiàn)一個合適的 WSGI 應(yīng)用,后者處理模板。 Flask 也綁定了一些通用的標(biāo)準(zhǔn)庫包,比如 logging 。其它所有一切取決于擴(kuò)展。
本文主要分析了flask是在Werkezug基礎(chǔ)上如何構(gòu)建WSGI接口與路由系統(tǒng)的。

WSGI是什么?

WSGI的本質(zhì)是一種約定,是Python web開發(fā)中 web服務(wù)器與web應(yīng)用程序之間數(shù)據(jù)交互的約定。
網(wǎng)關(guān)協(xié)議的本質(zhì)是為了解耦,實現(xiàn)web服務(wù)器和web應(yīng)用程序的分離,WSGI就是一個支持WSGI的web服務(wù)器與Python web應(yīng)用程序之間的約定。

為了支持WSGI,服務(wù)器需要做什么?

在一起寫一個 Web 服務(wù)器(2)
中給出了一個支持WSGI的服務(wù)器實現(xiàn),下面的代碼以他為例。
一個WSGI服務(wù)器需要實現(xiàn)兩個函數(shù):
1.解析http請求,為應(yīng)用程序提供environ字典

    def get_environ(self):
        env = {}
        env["wsgi.version"]      = (1, 0)
        env["wsgi.url_scheme"]   = "http"
        env["wsgi.input"]        = StringIO.StringIO(self.request_data)
        env["wsgi.errors"]       = sys.stderr
        env["wsgi.multithread"]  = False
        env["wsgi.multiprocess"] = False
        env["wsgi.run_once"]     = False
        env["REQUEST_METHOD"]    = self.request_method    # GET
        env["PATH_INFO"]         = self.path              # /hello
        env["SERVER_NAME"]       = self.server_name       # localhost
        env["SERVER_PORT"]       = str(self.server_port)  # 8888
        return env

2.實現(xiàn)start response函數(shù)

    def start_response(self, status, response_headers, exc_info=None):
        # Add necessary server headers
        server_headers = [
            ("Date", "Tue, 31 Mar 2015 12:54:48 GMT"),
            ("Server", "WSGIServer 0.2"),
        ]
        self.headers_set = [status, response_headers + server_headers]
        # To adhere to WSGI specification the start_response must return
        # a "write" callable. We simplicity"s sake we"ll ignore that detail
        # for now.
        # return self.finish_response
WSGI服務(wù)器調(diào)用Python應(yīng)用程序

這里展示了服務(wù)器與應(yīng)用程序交互的過程:
1.從客戶端獲取到請求
2.通過get_env獲得envir變量
3.調(diào)用應(yīng)用程序,傳入env和start_response函數(shù),并獲得響應(yīng)
4.將響應(yīng)返回給客戶端

    def handle_one_request(self):
        self.request_data = request_data = self.client_connection.recv(1024)
        print("".join(
            "< {line}
".format(line=line)
            for line in request_data.splitlines()
        ))
 
        self.parse_request(request_data)
        env = self.get_environ()
        result = self.application(env, self.start_response)//調(diào)用應(yīng)用程序
        self.finish_response(result)
Python 應(yīng)用程序需要做什么?

在上述這個過程中,Python應(yīng)用程序需要做什么呢?
主要工作就是根據(jù)輸入的environ字典信息生成相應(yīng)的http報文返回給服務(wù)器。

from wsgiref.simple_server import make_server

def simple_app(environ, start_response):
    status = "200 OK"
    response_headers = [("Content-type", "text/plain")]
    start_response(status, response_headers)
    return [u"This is hello wsgi app".encode("utf8")]

httpd = make_server("", 8000, simple_app)
print "Serving on port 8000..."
httpd.serve_forever()
flask中如何實現(xiàn)WSGI接口

1.通過__call__方法將Flask對象變?yōu)榭烧{(diào)用

    def __call__(self, environ, start_response):
        """Shortcut for :attr:`wsgi_app`."""
        return self.wsgi_app(environ, start_response)

2.實現(xiàn)wsgi_app函數(shù)處理web服務(wù)器轉(zhuǎn)發(fā)的請求

    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)
路由是什么?

在web開發(fā)中,路由是指根據(jù)url分配到對應(yīng)的處理程序。
在上面的應(yīng)用中,一個包含了url路徑信息的environ對應(yīng)一個視圖函數(shù),問題就在于他只能處理一個固定的路由,如果我們需要根據(jù)我們的需求自由的綁定url和視圖函數(shù),這就需要我們自己建立一個新的間接層,這就是web框架的路由系統(tǒng)。

flask的路由是如何實現(xiàn)的?

Flask類中支持路由功能的數(shù)據(jù)結(jié)構(gòu),在__init__函數(shù)中初始化:

url_rule_class = Rule
self.url_map = Map()
self.view_functions = {}

Map和Rule是werkzeug中實現(xiàn)的映射類和路由類。

    >>> m = Map([
    ...     # Static URLs
    ...     Rule("/", endpoint="static/index"),
    ...     Rule("/about", endpoint="static/about"),
    ...     Rule("/help", endpoint="static/help"),
    ...     # Knowledge Base
    ...     Subdomain("kb", [
    ...         Rule("/", endpoint="kb/index"),
    ...         Rule("/browse/", endpoint="kb/browse"),
    ...         Rule("/browse//", endpoint="kb/browse"),
    ...         Rule("/browse//", endpoint="kb/browse")
    ...     ])
    ... ], default_subdomain="www")

這里我們注意到Map類先建立了url到endpoint的映射,這樣做的目的是為了實現(xiàn)動態(tài)路由功能。

而view_functions是一個字典,它負(fù)責(zé)建立endpoint和視圖函數(shù)之間的映射關(guān)系。
下面是一個小實驗,證明我們所說的映射關(guān)系

>>> from flask import Flask
>>> app = Flask(__name__)
>>> @app.route("/")
... def index():
...     return "hello world"
... 
>>> app.url_map
Map([ index>,
 " (HEAD, GET, OPTIONS) -> static>])
>>> app.view_functions
{"index": , "static": >}

這里我們可以看到從 index>,"index": ,通過endpoint這個中間量,我們讓把路由和函數(shù)建立了映射關(guān)系。
要注意一下,為什么會有"/static/"這個路由呢,這是應(yīng)為在初始化時flask調(diào)用了add_url_rule函數(shù)做了如下綁定:

        if self.has_static_folder:
            assert bool(static_host) == host_matching, "Invalid static_host/host_matching combination"
            self.add_url_rule(
                self.static_url_path + "/",
                endpoint="static",
                host=static_host,
                view_func=self.send_static_file
            )
注冊路由

在flask中注冊路由有兩種方式,一種是用route裝飾器,如上所示,另一種是直接調(diào)用add_url_rule函數(shù)綁定視圖類,但是本質(zhì)上二者都是調(diào)用add_url_rule函數(shù),下面我們來看一下add_url_rule函數(shù)的實現(xiàn)。
在Flask的add_url_rule函數(shù)很長,但是核心的代碼為以下幾行:

self.url_map.add(rule)
rule = self.url_rule_class(rule, methods=methods, **options)
self.view_functions[endpoint] = view_func

1.裝飾器

def route(self, rule, **options):
        def decorator(f):
            endpoint = options.pop("endpoint", None)
            self.add_url_rule(rule, endpoint, f, **options)
            return f
        return decorator

2.視圖類

        class CounterAPI(MethodView):
            def get(self):
                return session.get("counter", 0)
            def post(self):
                session["counter"] = session.get("counter", 0) + 1
                return "OK"
        app.add_url_rule("/counter", view_func=CounterAPI.as_view("counter"))

注冊路由之后,flask就需要分發(fā)路由,調(diào)用相應(yīng)的視圖函數(shù)。

def dispatch_request(self):
        req = _request_ctx_stack.top.request
        if req.routing_exception is not None:
            self.raise_routing_exception(req)
        rule = req.url_rule
        if getattr(rule, "provide_automatic_options", False) 
           and req.method == "OPTIONS":
            return self.make_default_options_response()
        return self.view_functions[rule.endpoint](**req.view_args)

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

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/41115.html

相關(guān)文章

  • flask 源碼解析:簡介

    摘要:簡介官網(wǎng)上對它的定位是一個微開發(fā)框架。另外一個必須理解的概念是,簡單來說就是一套和框架應(yīng)用之間的協(xié)議。功能比較豐富,支持解析自動防止攻擊繼承變量過濾器流程邏輯支持代碼邏輯集成等等。那么,從下一篇文章,我們就正式開始源碼之旅了 文章屬于作者原創(chuàng),原文發(fā)布在個人博客。 flask 簡介 Flask 官網(wǎng)上對它的定位是一個微 python web 開發(fā)框架。 Flask is a micro...

    megatron 評論0 收藏0
  • flask源碼走讀

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

    Coly 評論0 收藏0
  • 如何理解Nginx, WSGI, Flask之間的關(guān)系

    摘要:通過查閱了些資料,總算把它們的關(guān)系理清了。在這個過程中,服務(wù)器的作用是接收請求處理請求返回響應(yīng)服務(wù)器是一類特殊的服務(wù)器,其作用是主要是接收請求并返回響應(yīng)。正是為了替代而出現(xiàn)的。三結(jié)語最后以,,之間的對話結(jié)束本文。 剛轉(zhuǎn)行互聯(lián)網(wǎng)行業(yè),聽到了許多名詞:Flask、Django、WSGI、 Nginx、Apache等等,一直無法搞清楚這些開源項目之間的關(guān)系,直至看到這篇文章后感覺醍醐灌頂,以...

    魏明 評論0 收藏0
  • flask 源碼解析:應(yīng)用啟動流程

    摘要:中有一個非常重要的概念每個應(yīng)用都是一個可調(diào)用的對象。它規(guī)定了的接口,會調(diào)用,并傳給它兩個參數(shù)包含了請求的所有信息,是處理完之后需要調(diào)用的函數(shù),參數(shù)是狀態(tài)碼響應(yīng)頭部還有錯誤信息。一般來說,嵌套的最后一層是業(yè)務(wù)應(yīng)用,中間就是。 文章屬于作者原創(chuàng),原文發(fā)布在個人博客。 WSGI 所有的 python web 框架都要遵循 WSGI 協(xié)議,如果對 WSGI 不清楚,可以查看我之前的介紹文章。 ...

    whatsns 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<