本文目錄一覽:
- 1、如何理解Nginx,uWSGI和Flask之間的關係
- 2、使用flask開發的網站有哪些
- 3、flask 比 php 好在哪裡
- 4、如何用 flask 優雅的實現 restful api
- 5、python輕量框架–Flask(入門教程)
如何理解Nginx,uWSGI和Flask之間的關係
總括來說,客戶端從發送一個 HTTP 請求到 Flask 處理請求,分別經過了 web 伺服器層,WSGI層,web框架層,這三個層次。不同的層次其作用也不同,下面簡要介紹各層的作用。
圖1:web伺服器,web框架與 WSGI 的三層關係
Web伺服器層
對於傳統的客戶端 – 伺服器架構,其請求的處理過程是,客戶端向伺服器發送請求,伺服器接收請求並處理請求,然後給客戶端返迴響應。在這個過程中,伺服器的作用是:
接收請求
處理請求
返迴響應
Web伺服器是一類特殊的伺服器,其作用是主要是接收 HTTP 請求並返迴響應。提起 web伺服器大家都不會陌生,常見的 web伺服器有 Nginx,Apache,IIS等。在上圖1的三層結構中,web伺服器是最先接收用戶請求的,並將響應結果返回給用戶。
Web框架層
Web框架的作用主要是方便我們開發 web應用程序,HTTP請求的動態數據就是由 web框架層來提供的。常見的 web框架有Flask,Django等,我們以 Flask 框架為例子,展示 web框架的作用:
Python
from flask import Flask
app = Flask(__name__)
@app.route(‘/hello’)
def hello_world():
return ‘Hello World!’
if __name__ == ‘__main__’:
app.run(host=’0.0.0.0′, port=8080)
1
2
3
4
5
6
7
from flask import Flask
app = Flask(__name__)
@app.route(‘/hello’)
def hello_world():
return ‘Hello World!’
if __name__ == ‘__main__’:
app.run(host=’0.0.0.0′, port=8080)
以上簡單的幾行代碼,就創建了一個 web應用程序對象 app。 app 監聽機器所有 ip 的 8080
埠,接受用戶的請求連接。我們知道,HTTP 協議使用 URL 來定位資源,上面的程序會將路徑 /hello 的請求交由 hello_world
方法處理, hello_world 返回 『Hello World!』 字元串。對於 web框架的使用者來說,他們並不關心如何接收 HTTP
請求,也不關心如何將請求路由到具體方法處理並將響應結果返回給用戶。Web框架的使用者在大部分情況下,只需要關心如何實現業務的邏輯即可。
WSGI層
WSGI 不是伺服器,也不是用於與程序交互的API,更不是真實的代碼,WSGI 只是一種介面,它只適用於 Python 語言,其全稱為
Web Server Gateway Interface,定義了 web伺服器和 web應用之間的介面規範。也就是說,只要 web伺服器和
web應用都遵守WSGI協議,那麼 web伺服器和 web應用就可以隨意的組合。
下面的代碼展示了 web伺服器是如何與 web應用組合在一起的
Python
def application(env, start_response):
start_response(‘200 OK’, [(‘Content-Type’, ‘text/html’)])
return [b”Hello World”]
1
2
3
def application(env, start_response):
start_response(‘200 OK’, [(‘Content-Type’, ‘text/html’)])
return [b”Hello World”]
方法 application由 web伺服器調用,參數 env, start_response 由 web伺服器實現並傳入。其中,
env是一個字典,包含了類似 HTTPHOST,HOSTUSERAGENT,SERVERPROTOCO 等環境變數。
start_response則是一個方法,該方法接受兩個參數,分別是 status, response_headers。
application方法的主要作用是,設置 http 響應的狀態碼和 Content-Type 等頭部信息,並返迴響應的具體結果。
上述代碼就是一個完整的 WSGI 應用,當一個支持 WSGI 的 web伺服器接收到客戶端的請求後,便會調用這個 application
方法。WSGI 層並不需要關心 env, start_response 這兩個變數是如何實現的,就像在 application
裡面所做的,直接使用這兩個變數即可。
值得指出的是,WSGI 是一種協議,需要區分幾個相近的名詞:
uwsgi:同 wsgi 一樣也是一種協議,uWSGI伺服器正是使用了 uwsgi 協議
uWSGI:實現了 uwsgi 和 WSGI 兩種協議的web伺服器。注意 uWSGI 本質上也是一種 web伺服器,處於上面描述的三層結構中的 web伺服器層。
CGI:通用網關介面,並不限於 Python 語言,定義了 web伺服器是如何向客戶端提供動態的內容。例如,規定了客戶端如何將參數傳遞給 web伺服器,web伺服器如何將參數傳遞給 web應用,web應用如何將它的輸出如何發送給客戶端,等等。
生產環境下的 web應用都不使用 CGI 了,CGI進程(類似 Python 解釋器)針對每個請求創建,用完就拋棄,效率低下。WSGI 正是為了替代 CGI 而出現的。
說到這,我們基本理清了 WSGI 在 web伺服器與 web框架之間作用:WSGI 就像一條紐帶,將 web伺服器與
web框架連接起來。回到本文的題目,Nginx 屬於一種 web伺服器,Flask屬於一種 web框架,因此,WSGI 與
Nginx、Flask 的作用就不明而喻了。
Nginx,WSGI,Flask 之間的對話
Nginx:Hey,WSGI,我剛收到了一個請求,我需要你作些準備,然後由Flask來處理這個請求。
WSGI:OK,Nginx。我會設置好環境變數,然後將這個請求傳遞給Flask處理。
Flask:Thanks WSGI!給我一些時間,我將會把請求的響應返回給你。
WSGI:Alright,那我等你。
Flask:Okay,我完成了,這裡是請求的響應結果,請求把結果傳遞給Nginx。 WSGI:Good job!
Nginx,這裡是響應結果,已經按照要求給你傳遞迴來了。
Nginx:Cool,我收到了,我把響應結果返回給客戶端。大家合作愉快~
使用flask開發的網站有哪些
Python 生態圈有兩個現象級的 Web 框架 Flask, Django.
兩個框架風格迥異, 但是都各自帶動了龐大的生態圈, 這得益於二者靈活的擴展能力.
本書講述的是基於 Flask 開發 Web 項目.
在對 Flask 框架的各個部分簡要分析後, 本書介紹了
* 表單處理(Flask-WTF)
* 持久化(Flask-SQLAlchemy, 這貨作者就是 Flask 的作者喲)
* 郵件
* 配置
* 一個真實案例: 模型, 用戶驗證, 角色, 關注, 寫template, 寫API
# 特點
* 線程局部變數
我不知道該把這個稱作特點還是缺點.
至少在Flask的文檔中作者明確給出這樣的解釋: 作為一個碼農, 你也許會感到不適, 但我就想這樣設計.
大部分的 Web 框架, 請求對象是外部注入的, 唯獨 Flask 選擇了全局 (flask.request, flask.g).
這個特點存在意味著你要小心使用這個特性, 否則很容易遇上需要調試大半天的Bug.
另外, request 不是那麼容易造出來的.
不過, 這不是什麼大不了的事情.
這個順便波及到測試, 測試的setup 與 teardown, 你必須去營造一個上下文, 關於這點, 書中有講解如何操作.
* Route/Template
框架的路由使用的是Werkzeug.
Template使用的是Jinja2, 當然不喜歡的話, 用別的也很簡單.
* 足夠小
Flask 只封裝了請求, 路由, 模板這麼幾個功能.
用起來容易, 要寫好也得費點腦子漲點經驗才行.
說穿了也就是一句話:
The idea of Flask is to build a good foundation for all applications.
Everything else is up to you or extensions.
[Ref: What Flask is, What Flask is Not]()
# 工作流
常規的三板斧: 開發, 測試, 部署.
書裡面的部署和配置這兩章節講的很出色, 值得一讀, 我給打五星.
# 插件
借用 @死魚眼28號 常說的一句話, 很多 Flask 插件都寫得很渣.
我表示 +1.
挑選插件時記得看下插件源碼, 給作者的碼力打個分再決定要不要用.
# 後記
關於 Web 開發, 我們的選擇有很多:
* PHP(Laravel, CodeIgniter, Yii, Symfony, CakePHP, etc.)
* Ruby(RoR, Sinatra, etc.)
* Python(Flask, Django, Quixote, Web.py, Bottle, etc.)
* Java/Scala(Spring, Play!, etc.)
殊途同歸, 他們也給出了幾乎一樣的解決方案.
我們可以看到大部分的 Web 項目都有著類似的目錄分類, 類似的架構.
Flask 也不外乎如此: 幫你包裝好請求對象, 剩下的路由, 路由邏輯, 響應內容你來填.
上面大部分框架從大學到工作或多或少使用過, 其實真正寫到業務層面時, 框架那些都不是事兒.
你想要的東西, 或框架自己造, 或慫恿隊友幫你造, 或你自己造, 總之基本上你總能拿到你要的信息.
不要被框架局限了視野喲.
flask 比 php 好在哪裡
flask 是python的一個框架
而php是一種編輯語言
你來告訴我:怎麼比?
如何用 flask 優雅的實現 restful api
首先,安裝Flask
pip install flask
閱讀這篇文章之前我假設你已經了解RESTful API的相關概念,如果不清楚,可以閱讀我之前寫的這篇博客[Designing a RESTful Web API
Flask是一個使用Python開發的基於Werkzeug的Web框架。
Flask非常適合於開發RESTful API,因為它具有以下特點:
?使用Python進行開發,Python簡潔易懂
?容易上手
?靈活
?可以部署到不同的環境
?支持RESTful請求分發
我一般是用curl命令進行測試,除此之外,還可以使用Chrome瀏覽器的postman擴展。
資源
首先,我創建一個完整的應用,支持響應/, /articles以及/article/:id。
from flask import Flask, url_for
app = Flask(__name__)
@app.route(‘/’)
def api_root():
return ‘Welcome’
@app.route(‘/articles’)
def api_articles():
return ‘List of ‘ + url_for(‘api_articles’)
@app.route(‘/articles/articleid’)
def api_article(articleid):
return ‘You are reading ‘ + articleid
if __name__ == ‘__main__’:
app.run()
可以使用curl命令發送請求:
響應結果分別如下所示:
GET /
Welcome
GET /articles
List of /articles
GET /articles/123
You are reading 123
路由中還可以使用類型定義:
@app.route(‘/articles/articleid’)
上面的路由可以替換成下面的例子:
@app.route(‘/articles/int:articleid’)
@app.route(‘/articles/float:articleid’)
@app.route(‘/articles/path:articleid’)
默認的類型為字元串。
請求
請求參數
假設需要響應一個/hello請求,使用get方法,並傳遞參數name
from flask import request
@app.route(‘/hello’)
def api_hello():
if ‘name’ in request.args:
return ‘Hello ‘ + request.args[‘name’]
else:
return ‘Hello John Doe’
伺服器會返回如下響應信息:
GET /hello
Hello John Doe
GET /hello?name=Luis
Hello Luis
請求方法
Flask支持不同的請求方法:
@app.route(‘/echo’, methods = [‘GET’, ‘POST’, ‘PATCH’, ‘PUT’, ‘DELETE’])
def api_echo():
if request.method == ‘GET’:
return “ECHO: GET\n”
elif request.method == ‘POST’:
return “ECHO: POST\n”
elif request.method == ‘PATCH’:
return “ECHO: PACTH\n”
elif request.method == ‘PUT’:
return “ECHO: PUT\n”
elif request.method == ‘DELETE’:
return “ECHO: DELETE”
可以使用如下命令進行測試:
curl -X PATCH :5000/echo
不同請求方法的響應如下:
GET /echo
ECHO: GET
POST /ECHO
ECHO: POST
…
請求數據和請求頭
通常使用POST方法和PATCH方法的時候,都會發送附加的數據,這些數據的格式可能如下:普通文本(plain text), JSON,XML,二進位文件或者用戶自定義格式。
Flask中使用request.headers類字典對象來獲取請求頭信息,使用request.data 獲取請求數據,如果發送類型是application/json,則可以使用request.get_json()來獲取JSON數據。
from flask import json
@app.route(‘/messages’, methods = [‘POST’])
def api_message():
if request.headers[‘Content-Type’] == ‘text/plain’:
return “Text Message: ” + request.data
elif request.headers[‘Content-Type’] == ‘application/json’:
return “JSON Message: ” + json.dumps(request.json)
elif request.headers[‘Content-Type’] == ‘application/octet-stream’:
f = open(‘./binary’, ‘wb’)
f.write(request.data)
f.close()
return “Binary message written!”
else:
return “415 Unsupported Media Type ;)”
使用如下命令指定請求數據類型進行測試:
curl -H “Content-type: application/json” \
-X POST :5000/messages -d ‘{“message”:”Hello Data”}’
使用下面的curl命令來發送一個文件:
curl -H “Content-type: application/octet-stream” \
-X POST :5000/messages –data-binary @message.bin
不同數據類型的響應結果如下所示:
POST /messages {“message”: “Hello Data”}
Content-type: application/json
JSON Message: {“message”: “Hello Data”}
POST /message message.bin
Content-type: application/octet-stream
Binary message written!
注意Flask可以通過request.files獲取上傳的文件,curl可以使用-F選項模擬上傳文件的過程。
響應
Flask使用Response類處理響應。
from flask import Response
@app.route(‘/hello’, methods = [‘GET’])
def api_hello():
data = {
‘hello’ : ‘world’,
‘number’ : 3
}
js = json.dumps(data)
resp = Response(js, status=200, mimetype=’application/json’)
resp.headers[‘Link’] = ”
return resp
使用-i選項可以獲取響應信息:
curl -i :5000/hello
返回的響應信息如下所示:
GET /hello
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 31
Link:
Server: Werkzeug/0.8.2 Python/2.7.1
Date: Wed, 25 Apr 2012 16:40:27 GMT
{“hello”: “world”, “number”: 3}
mimetype指定了響應數據的類型。
上面的過程可以使用Flask提供的一個簡便方法實現:
from flask import jsonify
…
# 將下面的代碼替換成
resp = Response(js, status=200, mimetype=’application/json’)
# 這裡的代碼
resp = jsonify(data)
resp.status_code = 200
狀態碼和錯誤處理
如果成功響應的話,狀態碼為200。對於404錯誤我們可以這樣處理:
@app.errorhandler(404)
def not_found(error=None):
message = {
‘status’: 404,
‘message’: ‘Not Found: ‘ + request.url,
}
resp = jsonify(message)
resp.status_code = 404
return resp
@app.route(‘/users/userid’, methods = [‘GET’])
def api_users(userid):
users = {‘1′:’john’, ‘2’:’steve’, ‘3’:’bill’}
if userid in users:
return jsonify({userid:users[userid]})
else:
return not_found()
測試上面的兩個URL,結果如下:
GET /users/2
HTTP/1.0 200 OK
{
“2”: “steve”
}
GET /users/4
HTTP/1.0 404 NOT FOUND
{
“status”: 404,
“message”: “Not Found: :5000/users/4”
}
默認的Flask錯誤處理可以使用@error_handler修飾器進行覆蓋或者使用下面的方法:
app.error_handler_spec[None][404] = not_found
即使API不需要自定義錯誤信息,最好還是像上面這樣做,因為Flask默認返回的錯誤信息是HTML格式的。
認證
使用下面的代碼可以處理 HTTP Basic Authentication。
from functools import wraps
def check_auth(username, password):
return username == ‘admin’ and password == ‘secret’
def authenticate():
message = {‘message’: “Authenticate.”}
resp = jsonify(message)
resp.status_code = 401
resp.headers[‘WWW-Authenticate’] = ‘Basic realm=”Example”‘
return resp
def requires_auth(f):
@wraps(f)
def decorated(*args, **kwargs):
auth = request.authorization
if not auth:
return authenticate()
elif not check_auth(auth.username, auth.password):
return authenticate()
return f(*args, **kwargs)
return decorated
接下來只需要給路由增加@require_auth修飾器就可以在請求之前進行認證了:
@app.route(‘/secrets’)
@requires_auth
def api_hello():
return “Shhh this is top secret spy stuff!”
現在,如果沒有通過認證的話,響應如下所示:
GET /secrets
HTTP/1.0 401 UNAUTHORIZED
WWW-Authenticate: Basic realm=”Example”
{
“message”: “Authenticate.”
}
curl通過-u選項來指定HTTP basic authentication,使用-v選項列印請求頭:
curl -v -u “admin:secret”
響應結果如下:
GET /secrets Authorization: Basic YWRtaW46c2VjcmV0
Shhh this is top secret spy stuff!
Flask使用MultiDict來存儲頭部信息,為了給客戶端展示不同的認證機制,可以給header添加更多的WWW-Autheticate。
resp.headers[‘WWW-Authenticate’] = ‘Basic realm=”Example”‘resp.headers.add(‘WWW-Authenticate’, ‘Bearer realm=”Example”‘)
調試與日誌
通過設置debug=True來開啟調試信息:
app.run(debug=True)
使用Python的logging模塊可以設置日誌信息:
import logging
file_handle(‘app.log’)
app.logger.addHandler(file_handler)
app.logger.setLevel(logging.INFO)
@app.route(‘/hello’, methods = [‘GET’])
def api_hello():
app.logger.info(‘informing’)
app.logger.warning(‘warning’)
app.logger.error(‘screaming bloody murder!’)
return “check your logs\n”
CURL 命令參考
選項
作用
-X 指定HTTP請求方法,如POST,GET
-H 指定請求頭,例如Content-type:application/json
-d 指定請求數據
–data-binary 指定發送的文件
-i 顯示響應頭部信息
-u 指定認證用戶名與密碼
-v 輸出請求頭部信息
python輕量框架–Flask(入門教程)
1.建立: F:\Python\flask文件夾路徑
2.安裝virtualenv,在此路徑下打開命令行窗口輸入:
3.新建一個目錄,並在裡邊創建virtualenv環境,在DOS下
如圖:
這時你創建的myproject文件夾裡面就多了一個venv文件夾:
4.激活虛擬環境
現在命令行前面多了個(venv)表示你在venv環境內
5.在virtualenv里安裝Flask
完成。如圖:
6.驗證是否安裝,你可以進入 Python 解釋器,嘗試導入 Flask:
如果沒有報錯,那麼就安裝成功了~如圖:
1.在myproject文件夾下打開命令行:
cd app #進入app文件夾
mkdir static
mkdir templates
我們的應用程序包是放置於 app 文件夾中。子文件夾 static 是我們存放靜態文件像圖片,JS文件以及樣式文件。子文件夾 templates 顯然是存放模板文件。
2.為我們的 app 包(文件 app/ init .py )創建一個簡單的初始化腳本:
上面的腳本簡單地創建應用對象,接著導入視圖模塊,該模塊我們暫未編寫。
視圖是響應來自網頁瀏覽器的請求的處理器。在 Flask 中,視圖是編寫成 Python 函數。每一個視圖函數是映射到一個或多個請求的 URL。
3.讓我們編寫第一個視圖函數(文件 app/views.py ):
其實這個視圖是非常簡單,它只是返回一個字元串,在客戶端的網頁瀏覽器上顯示。兩個 route 裝飾器創建了從網址 / 以及 /index 到這個函數的映射。
4.能夠完整工作的 Web 應用程序的最後一步是創建一個腳本,啟動我們的應用程序的開發 Web 伺服器。讓我們稱這個腳本為 run.py,並把它置於根目錄:
這個腳本簡單地從我們的 app 包中導入 app 變數並且調用它的 run 方法來啟動伺服器。請記住 app 變數中含有我們在之前創建的 Flask 實例。
5.要啟動應用程序,您只需運行此腳本(run.py)
如圖:
6.在伺服器初始化後,它將會監聽 5000 埠等待著連接。現在打開你的網頁瀏覽器輸入如下 URL:
另外你也可以使用這個 URL:
你看清楚了路由映射是如何工作的嗎?第一個 URL 映射到 /,而第二個 URL 映射到 /index。這兩個路由都關聯到我們的視圖函數,因此它們的作用是一樣的。如果你輸入其它的網址,你將會獲得一個錯誤,因為只有這兩個 URL 映射到視圖函數。
你可以通過 Ctrl-C 來終止伺服器
入門就到這裡,比較簡單的。
下一章:
python輕量框架–Flask(模板詳細版)
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/251001.html