RM新时代足球交易平台

18600329666

咨詢技術(shù)專家

掃一掃
與技術(shù)專家在線溝通

Menu
Tornado+Flask-Python web框架的使用

Tornado+Flask-Python web框架的使用,本文從框架介紹,框架對比及框架使用等三個方面介紹

web開發(fā)

1、Web框架介紹

瀏覽器上網(wǎng)的過程簡單來說就是客戶端和服務(wù)器的交互過程,在物理服務(wù)器上運行著服務(wù)器程序,永久地等待客戶端(主要是瀏覽器,比如Chrome,F(xiàn)irefox等)發(fā)送請求。通常服務(wù)器程序包含了 Web服務(wù)器和Web應(yīng)用兩部分,Web服務(wù)器接收客戶端的請求后,由Web應(yīng)用對瀏覽器的請求進行處理,將生成的響應(yīng)傳遞給Web服務(wù)器,再由Web服務(wù)器返回給客戶端。
圖片描述為了簡化Web應(yīng)用的開發(fā),使開發(fā)者可以專注于編寫業(yè)務(wù)邏輯代碼而無需關(guān)心Web應(yīng)用內(nèi)各模塊連接之類的重復(fù)性工作,繼而在Web應(yīng)用上產(chǎn)生了Web框架。一般Web框架的架構(gòu)如下圖所示,基于Python的Web框架如Django、tornado、flask、webpy等都在這個范圍內(nèi)進行不同的調(diào)整。如何在建立的Web服務(wù)器上運行一個Django應(yīng)用或Flask應(yīng)用,而無需對這些web框架或Web服務(wù)器做任何改變?WSGI協(xié)議可將web框架和web服務(wù)器分開,開發(fā)者可選擇適合自己的配對,混合匹配web框架和web服務(wù)器,對于服務(wù)器和框架開發(fā)者提供便利使他們可以專注于自己偏愛的領(lǐng)域和專長而不至于相互牽制。

這里我們把WSGI、uwsgi、uWSGI這幾個概念整理下:
WSGI(Web Server Gateway Interface)是為Python定義的Web服務(wù)器和Web應(yīng)用程序或框架之間的一種簡單而通用的接口協(xié)議,主要包括服務(wù)器和應(yīng)用程序兩部分,是描述了web服務(wù)器如何與web應(yīng)用程序通信的規(guī)范。
uwsgi基于二進制的線路協(xié)議,與WSGI通信協(xié)議作用相同,屬于uWSGI服務(wù)器的獨占協(xié)議,用于定義傳輸信息的類型(type of information)。
uWSGI是一個web服務(wù)器,實現(xiàn)了WSGI協(xié)議、uwsgi協(xié)議、http協(xié)議等。

2、Django、Tornado和Flask框架對比

在Python的web開發(fā)框架中,目前使用量最高的有Django、Flask和Tornado, 經(jīng)常會有人拿這幾個對比,相信大家的初步印象應(yīng)該是 Django大而全、Flask小而精、Tornado性能高。
Django是Python 中最全能的 web 開發(fā)框架,走大而全的方向。它最出名的是其全自動化的管理后臺:只需要使用起ORM,做簡單的對象定義,它就能自動生成數(shù)據(jù)庫結(jié)構(gòu)、以及全功能的管理后臺。不過Django提供的方便,也意味著Django內(nèi)置的ORM跟框架內(nèi)的其他模塊耦合程度高,深度綁定了該框架,應(yīng)用程序必須使用Django內(nèi)置的ORM,否則就不能享受到框架內(nèi)提供的種種基于其ORM的優(yōu)秀特性。
Tornado全稱Tornado Web Server,是一個用Python語言寫成的Web服務(wù)器兼Web應(yīng)用框架。Tornado走的是少而精的方向,注重的是性能優(yōu)越,它最出名的是異步非阻塞的服務(wù)器方式。(Tornado框架和服務(wù)器一起組成一個WSGI的全棧替代品。單獨在WSGI容器中使用tornado web框架或者tornaod http服務(wù)器,有一定的局限性,為了最大化的利用tornado的性能,推薦同時使用tornaod的web框架和HTTP服務(wù)器。)
Flask是一個使用 Python 編寫的輕量級 Web 應(yīng)用框架,也被稱為 “microframework”,語法簡單,部署很方便,整個框架自帶了路徑映射、模板引擎(Jinja2)、簡單的數(shù)據(jù)庫訪問等web框架組件,支持WSGI協(xié)議(采用 Werkzeug)。Flask使用 BSD 授權(quán)。 Flask使用簡單的核心,用 extension 增加其他功能,雖然沒有默認使用的數(shù)據(jù)庫、窗體驗證工具,然而Flask保留了擴增的彈性,可以用Flask-extension加入ORM、窗體驗證工具、文件上傳、各種開放式身份驗證技術(shù)這些功能。
從性能上看Tornado 比Django、Flask等主流 Web 服務(wù)器框架相比有著明顯的區(qū)別:它是非阻塞式服務(wù)器,速度相當快。然而 Tornado 相比 Django 和Flask屬于較為原始的框架,插件少,許多內(nèi)容需要自己去處理。而Flask插件多,文檔非常專業(yè),有專門的公司團隊維護,對于快速開發(fā)很有效率。由于WSGI協(xié)議的存在,可以結(jié)合 Tornado 的服務(wù)器異步特性、并發(fā)處理能力和Flask的文檔和擴展能力為一體。雖然像Django,F(xiàn)lask框架都有自己實現(xiàn)的簡單的WSGI服務(wù)器,但一般用于服務(wù)器調(diào)試,生產(chǎn)環(huán)境下建議用其他WSGI服務(wù)器,比如Nginx+uwsgi+Django方式。

Tornado關(guān)于使用平臺的說明:
Tornado 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). Tornado will also run on Windows, although this configuration is not officially supported and is recommended only for development use.
Tornado應(yīng)該運行在類Unix平臺,在線上部署時為了最佳的性能和擴展性,僅推薦Linux和BSD(因為充分利用Linux的epoll工具和BSD的kqueue工具,是Tornado不依靠多進程/多線程而達到高性能的原因)。對于Mac OS X,雖然也是衍生自BSD并且支持kqueue,但是其網(wǎng)絡(luò)性能通常不太給力,因此僅推薦用于開發(fā)。對于Windows,Tornado官方?jīng)]有提供配置支持,但是也可以運行起來,不過僅推薦在開發(fā)中使用。

3、Tornado+ Flask實現(xiàn)方式

(1)首先,我們導(dǎo)入了 Flask 類,這個類的實例將會是我們的 WSGI 應(yīng)用程序。

from flask import Flask

(2)接下來,我們創(chuàng)建一個該類的實例app,第一個參數(shù)是應(yīng)用模塊或者包的名稱。 如果使用單一的模塊(如本例),應(yīng)該使用 name ,因為模塊的名稱將會因其作為單獨應(yīng)用啟動還是作為模塊導(dǎo)入而有不同( 也即是 ‘main’ 或?qū)嶋H的導(dǎo)入名)。這是必須的,這樣 Flask 才知道到哪去找模板、靜態(tài)文件等等。

app = Flask(__name__)

(3)然后,我們使用route()裝飾器把一個函數(shù)綁定到對應(yīng)的URL上,告訴 Flask什么樣的URL能觸發(fā)我們的函數(shù)。 這個函數(shù)的名字也在生成URL時被特定的函數(shù)采用,這個函數(shù)返回我們想要顯示在用戶瀏覽器中的信息。

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

(4)最后我們用 run() 函數(shù)來讓應(yīng)用運行在本地服務(wù)器上。 if name == ‘main’: 確保服務(wù)器只會在該腳本被 Python 解釋器直接執(zhí)行的時候才會運行,而不是作為模塊導(dǎo)入的時候。

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

(5)外部可訪問的服務(wù)器。如果你運行了這個服務(wù)器(app.run()),你會發(fā)現(xiàn)它只能從你自己的計算機上訪問,網(wǎng)絡(luò)中其它任何的地方都不能訪問。在調(diào)試模式下,用戶可以在你的計算機上執(zhí)行任意 Python 代碼。因此,這個行為是默認的。如果你禁用了 debug 或信任你所在網(wǎng)絡(luò)的用戶,你可以簡單修改調(diào)用 run() 的方法使你的服務(wù)器公開可用,如下:app.run(host=‘0.0.0.0’)這會讓操作系統(tǒng)監(jiān)聽所有公網(wǎng) IP。
(6)雖然 run() 方法適用于啟動本地的開發(fā)服務(wù)器,但是你每次修改代碼后都要手動重啟它。這樣并不夠優(yōu)雅,而且 Flask 可以做到更好。如果你啟用了調(diào)試支持,服務(wù)器會在代碼修改后自動重新載入,并在發(fā)生錯誤時提供一個相當有用的調(diào)試器。有兩種途徑來啟用調(diào)試模式。一種是直接在應(yīng)用對象上設(shè)置:

app.debug = True
app.run()

另一種是作為 run 方法的一個參數(shù)傳入:

app.run(debug=True)

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

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

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 文件夾里尋找模板。所以,如果你的應(yīng)用是個模塊,這個文件夾應(yīng)該與模塊同級;如果它是一個包,那么這個文件夾作為包的子目錄:
情況 1: 模塊:
/application.py
/templates
/hello.html
情況 2: 包:
/application
/init.py
/templates
/hello.html

在Tornado中,我們可以通過wsgi模塊下的WSGIContainer類運行其他WSGI應(yīng)用的,例如Flask、Bottle、Django應(yīng)用。
(1)創(chuàng)建了一個HTTP服務(wù)器實例http_server,因為服務(wù)器要服務(wù)于我們剛剛建立的web應(yīng)用,將接收到的客戶端請求通過web應(yīng)用中的路由映射表引導(dǎo)到對應(yīng)的handler中,所以在構(gòu)建http_server對象的時候需要傳入web應(yīng)用對象app。可以使用自身的web框架, 如果使用托管的應(yīng)用,將要托管的應(yīng)用以參數(shù)的形式傳入到WSGIContainer類中。

    http_server = HTTPServer(WSGIContainer(app))

(2)緊接著,我們定義這個服務(wù)器監(jiān)聽的端口,將服務(wù)器綁定到80端口。

    http_server.listen(80)

(3)IOLoop 是 Tornado 的核心I/O循環(huán)調(diào)度模塊,也是tornado高性能的基石,封裝了Linux的epoll和BSD的kqueue,用于處理 socket 相關(guān)的連接、響應(yīng)、異步讀寫等網(wǎng)絡(luò)事件。每個 Tornado 進程都會初始化一個全局唯一的 IOLoop 實例,在 IOLoop 中通過靜態(tài)方法 instance() 進行封裝,獲取 IOLoop 實例直接調(diào)用此方法即可啟動 IOLoop 實例,即啟動事件循環(huán)機制,配合非阻塞的 HTTP Server 工作。
如果是tornado.ioloop.IOLoop.current().start()語句,IOLoop.current()返回當前線程的IOLoop實例。IOLoop.start()啟動IOLoop實例的I/O循環(huán),同時服務(wù)器監(jiān)聽被打開。


RM新时代足球交易平台