搜尋
首頁後端開發Python教學Python Web 應用:WSGI基礎
Python Web 應用:WSGI基礎Mar 18, 2017 am 11:44 AM
python

本文由碼農網 – 蕭豪原創翻譯,轉載請看清文末的轉載要求,歡迎參與我們的付費投稿計畫!

在Django,Flask,Bottle和其他一切Python web 框架底層的是Web Server Gateway Interface,簡稱WSGI。 WSGI對Python來說就像 Servlets對Java一樣——一種用於web伺服器並允許不同web伺服器和應用框架基於通用API交互的通用規範。然而,對於大多數事情,Python版本實作相當簡單。

WSGI被定義在PEP 3333協議裡面,如果在讀完本文之後你想學到更多東西的話,作者建議讀者先閱讀一下簡介。

本文將從一個應用開發者的角度來向你介紹WSGI說明,並且向你展示怎樣直接透過WSGI來開發應用程式(如果你迫不及待的話)。

你的第一個WSGI應用

下面是最基本的Python web應用:

def app(environ, start_fn):
    start_fn('200 OK', [('Content-Type', 'text/plain')])
    return ["Hello World!\n"]

就是這樣!整個文件。先命名為app.py然後在任何WSGI可編譯伺服器上面運行,然後你就可以得到一個Hello World並伴隨一個200的回應狀態碼。你可以使用gunicorn來完成,透過pip(pip install gunicorn)來安裝並執行gunicorn app:app。這條指令告訴gunicorn從應用程式模組裡的應用變數去取得可呼叫的WSGI。

剛才,十分興奮吧。僅僅三行程式碼就可以運行一個應用程式?那一定是某種意義上的記錄(不包括PHP,因為mod_php在起作用)。我敢打賭你現在一定想更深入了解下去了。

所以一個WSGI應用最重要的部分是什麼呢?

  • 一個WSGI應用是Python可調用的,就像一個函數,一個類,或者一個有__call__方法的類實例

  • 可調用的應用程式必須接受兩個參數:environ,一個包含必要資料的Python字典,start_fn,它本身是可呼叫的。

  • 應用程式必須能呼叫start_fn和兩個參數:狀態碼(字串),和一個頭部以兩個元組表述的列表。

  • 應用程式傳回一個在回傳體裡包含bytes的方便的可迭代對象,流式的部分-例如,一個個只包含「Hello,World!」字串的列表。 (如果app是一個類別的話,可以在__iter__方法裡完成)

例如下面兩個例子和第一個是等價的:

class app(object):

    def __init__(self, environ, start_fn):
        self.environ = environ
        self.start_fn = start_fn

    def __iter__(self):
        self.start_fn('200 OK', [('Content-Type', 'text/plain')])
        yield "Hello World!\n"
class Application(object):
    def __call__(self, environ, start_fn):
        start_fn('200 OK', [('Content-Type', 'text/plain')])
        yield "Hello World!\n"

app = Application()

你可能已經開始思考能用這些東西來做什麼了,但是最可能相關的一項是用來寫中間件。

讓它活躍起來

中間件是一種方便擴展WSGI應用功能性的方法。因為你只需提供一個可呼叫的對象,你可以任意把它包裹在其他函數裡。

例如,假設我們想偵測一下environ裡面的內容。我們可以輕易地建立一個中間件來完成,如下所示:

import pprint

def handler(environ, start_fn):
    start_fn('200 OK', [('Content-Type', 'text/plain')])
    return ["Hello World!\n"]

def log_environ(handler):
    def _inner(environ, start_fn):
        pprint.pprint(environ)
        return handler(environ, start_fn)
    return _inner

app = log_environ(handler)

這裡,log_environ是一個返回函數的函數,它在environ參數延遲原始回調之前裝飾該參數。

這樣寫中間件的優點是中間件和處理器不需要知道或關心對方。你可以輕易地綁定log_environ到一個Flask應用上面,例如,因為Flask應用是WSGI應用。

其他一些有用的中間件設計:

import pprint

def handle_error(handler):
    def _inner(environ, start_fn):
        try:
            return handler(environ, start_fn)
        except Exception as e:
            print e  # Log error
            start_fn('500 Server Error', [('Content-Type', 'text/plain')])
            return ['500 Server Error']
    return _inner

def wrap_query_params(handler):
    def _inner(environ, start_fn):
        qs = environ.get('QUERY_STRING')
        environ['QUERY_PARAMS'] = urlparse.parse_qs(qs)
        return handler(environ, start_fn)
    return _inner

如果你不想讓你的文件有一個很大的金字塔底的話,你可以使用reduce一次應用到多個中間件上。

# Applied from bottom to top on the way in, then top to bottom on the way out
MIDDLEWARES = [wrap_query_params,
               log_environ,
               handle_error]

app = reduce(lambda h, m: m(h), MIDDLEWARES, handler)

利用start_fn參數的優點你也可以寫裝飾響應體的中間件。下面是一個內容類型頭部是text/plain反轉輸出結果的中間件。

def reverser(handler):

    # A reverse function
    rev = lambda it: it[::-1]

    def _inner(environ, start_fn):
        do_reverse = []  # Must be a reference type such as a list

        # Override start_fn to check the content type and set a flag
        def start_reverser(status, headers):
            for name, value in headers:
                if (name.lower() == 'content-type'
                        and value.lower() == 'text/plain'):
                    do_reverse.append(True)
                    break

            # Remember to call `start_fn`
            start_fn(status, headers)

        response = handler(environ, start_reverser)

        try:
            if do_reverse:
                return list(rev(map(rev, response)))

            return response
        finally:
            if hasattr(response, 'close'):
                response.close()
    return _inner

由於start_fn和響應體的分離有一點混亂,但是還是完美運行的。

同時請注意,為了嚴格遵循WSGI規範,如果存在的話,我們必須在響應體裡檢查close方法並且調用它。 WSGI應用程式有可能傳回一個write函數而不是一個調用處理器的可迭代對象,如果你想要你的中間件支援更早的應用程式的話,你可能需要處理這個問題。

一旦你開始一點點把玩原生WSGI,你就開始理解為什麼Python有一堆web框架。 WSGI讓從底層造一些東西變得十分簡單。例如,你也許正在考慮下面的路由問題:

routes = {
    '/': home_handler,
    '/about': about_handler,
}

class Application(object):
    def __init__(self, routes):
        self.routes = routes

    def not_found(self, environ, start_fn):
        start_fn('404 Not Found', [('Content-Type', 'text/plain')])
        return ['404 Not Found']

    def __call__(self, environ, start_fn):
        handler = self.routes.get(environ.get('PATH_INFO')) or self.not_found
        return handler(environ, start_fn)

如果你喜歡下面資源集合的靈活性的話,直接使用WSGI造輪子還是十分方便的。

  • 模板庫:投入任何你喜歡的模板(例如,Jinja2,Pystashe)然後從你的處理器返回渲染後的模板!

  • 用一個函式庫來幫助你的路由,如Routes或Werkzeug’s routing。實際上,如果你想輕鬆使用WSGI的話,看看Werkzeug吧。

  • 使用任何Flask或相似的資料庫遷移庫。

當然,對於非專業的應用,你也可能想使用一下框架,那樣的話,一些特殊的諸如此類的例子也可以得到合理解決。

關於伺服器呢?

有許許多多服務WSGI應用的方法。我們已經討論過Gunicorn了,一個相當好的選擇。 uWSGI是另一個不錯的選擇。但請確保在服務這些靜態東西之前設定好nginx一類的東西,並且你應該有一個固定的開始節點。

以上是Python Web 應用:WSGI基礎的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
详细讲解Python之Seaborn(数据可视化)详细讲解Python之Seaborn(数据可视化)Apr 21, 2022 pm 06:08 PM

本篇文章给大家带来了关于Python的相关知识,其中主要介绍了关于Seaborn的相关问题,包括了数据可视化处理的散点图、折线图、条形图等等内容,下面一起来看一下,希望对大家有帮助。

详细了解Python进程池与进程锁详细了解Python进程池与进程锁May 10, 2022 pm 06:11 PM

本篇文章给大家带来了关于Python的相关知识,其中主要介绍了关于进程池与进程锁的相关问题,包括进程池的创建模块,进程池函数等等内容,下面一起来看一下,希望对大家有帮助。

Python自动化实践之筛选简历Python自动化实践之筛选简历Jun 07, 2022 pm 06:59 PM

本篇文章给大家带来了关于Python的相关知识,其中主要介绍了关于简历筛选的相关问题,包括了定义 ReadDoc 类用以读取 word 文件以及定义 search_word 函数用以筛选的相关内容,下面一起来看一下,希望对大家有帮助。

归纳总结Python标准库归纳总结Python标准库May 03, 2022 am 09:00 AM

本篇文章给大家带来了关于Python的相关知识,其中主要介绍了关于标准库总结的相关问题,下面一起来看一下,希望对大家有帮助。

Python数据类型详解之字符串、数字Python数据类型详解之字符串、数字Apr 27, 2022 pm 07:27 PM

本篇文章给大家带来了关于Python的相关知识,其中主要介绍了关于数据类型之字符串、数字的相关问题,下面一起来看一下,希望对大家有帮助。

分享10款高效的VSCode插件,总有一款能够惊艳到你!!分享10款高效的VSCode插件,总有一款能够惊艳到你!!Mar 09, 2021 am 10:15 AM

VS Code的确是一款非常热门、有强大用户基础的一款开发工具。本文给大家介绍一下10款高效、好用的插件,能够让原本单薄的VS Code如虎添翼,开发效率顿时提升到一个新的阶段。

详细介绍python的numpy模块详细介绍python的numpy模块May 19, 2022 am 11:43 AM

本篇文章给大家带来了关于Python的相关知识,其中主要介绍了关于numpy模块的相关问题,Numpy是Numerical Python extensions的缩写,字面意思是Python数值计算扩展,下面一起来看一下,希望对大家有帮助。

python中文是什么意思python中文是什么意思Jun 24, 2019 pm 02:22 PM

pythn的中文意思是巨蟒、蟒蛇。1989年圣诞节期间,Guido van Rossum在家闲的没事干,为了跟朋友庆祝圣诞节,决定发明一种全新的脚本语言。他很喜欢一个肥皂剧叫Monty Python,所以便把这门语言叫做python。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

WebStorm Mac版

WebStorm Mac版

好用的JavaScript開發工具