基於Python的web架構之Tornado+Flask

highhand發表於2021-09-09

1、Web框架介紹

瀏覽器上網的過程簡單來說就是客戶端和伺服器的互動過程,在物理伺服器上執行著伺服器程式,永久地等待客戶端(主要是瀏覽器,比如Chrome,Firefox等)傳送請求。通常伺服器程式包含了 Web伺服器和Web應用兩部分,Web伺服器接收客戶端的請求後,由Web應用對瀏覽器的請求進行處理,將生成的響應傳遞給Web伺服器,再由Web伺服器返回給客戶端。
圖片描述為了簡化Web應用的開發,使開發者可以專注於編寫業務邏輯程式碼而無需關心Web應用內各模組連線之類的重複性工作,繼而在Web應用上產生了Web框架。一般Web框架的架構如下圖所示,基於Python的Web框架如Django、tornado、flask、webpy等都在這個範圍內進行不同的調整。如何在建立的Web伺服器上執行一個Django應用或Flask應用,而無需對這些web框架或Web伺服器做任何改變?WSGI協議可將web框架和web伺服器分開,開發者可選擇適合自己的配對,混合匹配web框架和web伺服器,對於伺服器和框架開發者提供便利使他們可以專注於自己偏愛的領域和專長而不至於相互牽制。

這裡我們把WSGI、uwsgi、uWSGI這幾個概念整理下:
WSGI(Web Server Gateway Interface)是為Python定義的Web伺服器和Web應用程式或框架之間的一種簡單而通用的介面協議,主要包括伺服器和應用程式兩部分,是描述了web伺服器如何與web應用程式通訊的規範。
uwsgi基於二進位制的線路協議,與WSGI通訊協議作用相同,屬於uWSGI伺服器的獨佔協議,用於定義傳輸資訊的型別(type of information)。
uWSGI是一個web伺服器,實現了WSGI協議、uwsgi協議、http協議等。

2、Django、和Flask框架對比

在Python的web開發框架中,目前使用量最高的有Django、Flask和, 經常會有人拿這幾個對比,相信大家的初步印象應該是 Django大而全、Flask小而精、效能高。
Django是Python 中最全能的 web 開發框架,走大而全的方向。它最出名的是其全自動化的管理後臺:只需要使用起ORM,做簡單的物件定義,它就能自動生成資料庫結構、以及全功能的管理後臺。不過Django提供的方便,也意味著Django內建的ORM跟框架內的其他模組耦合程度高,深度繫結了該框架,應用程式必須使用Django內建的ORM,否則就不能享受到框架內提供的種種基於其ORM的優秀特性。
全稱 Web Server,是一個用Python語言寫成的Web伺服器兼Web應用框架。走的是少而精的方向,注重的是效能優越,它最出名的是非同步非阻塞的伺服器方式。(框架和伺服器一起組成一個WSGI的全棧替代品。單獨在WSGI容器中使用tornado web框架或者tornaod http伺服器,有一定的侷限性,為了最大化的利用tornado的效能,推薦同時使用tornaod的web框架和HTTP伺服器。)
Flask是一個使用 Python 編寫的輕量級 Web 應用框架,也被稱為 “microframework”,語法簡單,部署很方便,整個框架自帶了路徑對映、模板引擎(Jinja2)、簡單的資料庫訪問等web框架元件,支援WSGI協議(採用 Werkzeug)。Flask使用 BSD 授權。 Flask使用簡單的核心,用 extension 增加其他功能,雖然沒有預設使用的資料庫、窗體驗證工具,然而Flask保留了擴增的彈性,可以用Flask-extension加入ORM、窗體驗證工具、檔案上傳、各種開放式身份驗證技術這些功能。
從效能上看 比Django、Flask等主流 Web 伺服器框架相比有著明顯的區別:它是非阻塞式伺服器,速度相當快。然而 相比 Django 和Flask屬於較為原始的框架,外掛少,許多內容需要自己去處理。而Flask外掛多,文件非常專業,有專門的公司團隊維護,對於快速開發很有效率。由於WSGI協議的存在,可以結合 的伺服器非同步特性、併發處理能力和Flask的文件和擴充套件能力為一體。雖然像Django,Flask框架都有自己實現的簡單的WSGI伺服器,但一般用於伺服器除錯,生產環境下建議用其他WSGI伺服器,比如Nginx+uwsgi+Django方式。

關於使用平臺的說明:
should run on any Unix-like platform, although for the best performance and scalability only Linux (with epoll) and BSD (with kqueue) are recommended for production deployment (even though Mac OS X is derived from BSD and supports kqueue, its networking performance is generally poor so it is recommended only for development use). will also run on Windows, although this configuration is not officially supported and is recommended only for development use.
應該執行在類Unix平臺,線上上部署時為了最佳的效能和擴充套件性,僅推薦Linux和BSD(因為充分利用Linux的epoll工具和BSD的kqueue工具,是不依靠多程式/多執行緒而達到高效能的原因)。對於Mac OS X,雖然也是衍生自BSD並且支援kqueue,但是其網路效能通常不太給力,因此僅推薦用於開發。對於Windows,官方沒有提供配置支援,但是也可以執行起來,不過僅推薦在開發中使用。

3、+ Flask實現方式

(1)首先,我們匯入了 Flask 類,這個類的例項將會是我們的 WSGI 應用程式。

from flask import Flask

(2)接下來,我們建立一個該類的例項app,第一個引數是應用模組或者包的名稱。 如果使用單一的模組(如本例),應該使用 name ,因為模組的名稱將會因其作為單獨應用啟動還是作為模組匯入而有不同( 也即是 ‘main’ 或實際的匯入名)。這是必須的,這樣 Flask 才知道到哪去找模板、靜態檔案等等。

app = Flask(__name__)

(3)然後,我們使用route()裝飾器把一個函式繫結到對應的URL上,告訴 Flask什麼樣的URL能觸發我們的函式。 這個函式的名字也在生成URL時被特定的函式採用,這個函式返回我們想要顯示在使用者瀏覽器中的資訊。

@app.route('/', methods=['GET'])
def index(name = None):
    if request.method == 'GET':
        name = "WEB SERVER"
        return render_template('index.html',name=name)

(4)最後我們用 run() 函式來讓應用執行在本地伺服器上。 if name == ‘main’: 確保伺服器只會在該指令碼被 Python 直譯器直接執行的時候才會執行,而不是作為模組匯入的時候。

if __name__ == '__main__':
    try:
        app.run(host='0.0.0.0', port=80, debug=False)
    except:
        pass

(5)外部可訪問的伺服器。如果你執行了這個伺服器(app.run()),你會發現它只能從你自己的計算機上訪問,網路中其它任何的地方都不能訪問。在除錯模式下,使用者可以在你的計算機上執行任意 Python 程式碼。因此,這個行為是預設的。如果你禁用了 debug 或信任你所在網路的使用者,你可以簡單修改呼叫 run() 的方法使你的伺服器公開可用,如下:app.run(host=‘0.0.0.0’)這會讓作業系統監聽所有公網 IP。
(6)雖然 run() 方法適用於啟動本地的開發伺服器,但是你每次修改程式碼後都要手動重啟它。這樣並不夠優雅,而且 Flask 可以做到更好。如果你啟用了除錯支援,伺服器會在程式碼修改後自動重新載入,並在發生錯誤時提供一個相當有用的偵錯程式。有兩種途徑來啟用除錯模式。一種是直接在應用物件上設定:

app.debug = True
app.run()

另一種是作為 run 方法的一個引數傳入:

app.run(debug=True)

兩種方法的效果完全相同。

(1)用Python 生成 HTML 十分無趣,而且相當繁瑣,因為你必須手動對 HTML 做轉義來保證應用的安全。為此,Flask 配備了 Jinja2 模板引擎。你可以使用 render_template() 方法來渲染模板。你需要做的一切就是將模板名和你想作為關鍵字的引數傳入模板的變數。這裡有一個展示如何渲染模板的簡例:

from flask import render_template

@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):
    return render_template('hello.html', name=name)

Flask 會在 templates 資料夾裡尋找模板。所以,如果你的應用是個模組,這個資料夾應該與模組同級;如果它是一個包,那麼這個資料夾作為包的子目錄:
情況 1: 模組:
/application.py
/templates
/hello.html
情況 2: 包:
/application
/init.py
/templates
/hello.html

在中,我們可以透過wsgi模組下的WSGIContainer類執行其他WSGI應用的,例如Flask、Bottle、Django應用。
(1)建立了一個HTTP伺服器例項http_server,因為伺服器要服務於我們剛剛建立的web應用,將接收到的客戶端請求透過web應用中的路由對映表引導到對應的handler中,所以在構建http_server物件的時候需要傳入web應用物件app。可以使用自身的web框架, 如果使用託管的應用,將要託管的應用以引數的形式傳入到WSGIContainer類中。

    http_server = HTTPServer(WSGIContainer(app))

(2)緊接著,我們定義這個伺服器監聽的埠,將伺服器繫結到80埠。

    http_server.listen(80)

(3)IOLoop 是 的核心I/O迴圈排程模組,也是tornado高效能的基石,封裝了Linux的epoll和BSD的kqueue,用於處理 socket 相關的連線、響應、非同步讀寫等網路事件。每個 程式都會初始化一個全域性唯一的 IOLoop 例項,在 IOLoop 中透過靜態方法 instance() 進行封裝,獲取 IOLoop 例項直接呼叫此方法即可啟動 IOLoop 例項,即啟動事件迴圈機制,配合非阻塞的 HTTP Server 工作。
如果是tornado.ioloop.IOLoop.current().start()語句,IOLoop.current()返回當前執行緒的IOLoop例項。IOLoop.start()啟動IOLoop例項的I/O迴圈,同時伺服器監聽被開啟。

    IOLoop.instance().start()

(4)執行python 。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/810/viewspace-2818418/,如需轉載,請註明出處,否則將追究法律責任。

相關文章