使用python的Flask實現一個RESTful API伺服器端

2021-12-10 數據分析聯盟

最近這些年,REST已經成為web services和APIs的標準架構,很多APP的架構基本上是使用RESTful的形式了。

本文將會使用python的Flask框架輕鬆實現一個RESTful的服務。

REST的六個特性:

Client-Server:伺服器端與客戶端分離。

Stateless(無狀態):每次客戶端請求必需包含完整的信息,換句話說,每一次請求都是獨立的。

Cacheable(可緩存):伺服器端必需指定哪些請求是可以緩存的。

Layered System(分層結構):伺服器端與客戶端通訊必需標準化,伺服器的變更並不會影響客戶端。

Uniform Interface(統一接口):客戶端與伺服器端的通訊方法必需是統一的。

Code on demand(按需執行代碼?):伺服器端可以在上下文中執行代碼或者腳本?

Servers can provide executable code or scripts for clients to execute in their context. This constraint is the only one that is optional.(沒看明白)

RESTful web service的樣子

REST架構就是為了HTTP協議設計的。RESTful web services的核心概念是管理資源。資源是由URIs來表示,客戶端使用HTTP當中的'POST, OPTIONS, GET, PUT, DELETE'等方法發送請求到伺服器,改變相應的資源狀態。

HTTP請求方法通常也十分合適去描述操作資源的動作:

HTTP方法動作例子GET獲取資源信息

http://example.com/api/orders

(檢索訂單清單)

GET獲取資源信息

http://example.com/api/orders/123

(檢索訂單 #123)

POST創建一個次的資源

http://example.com/api/orders

(使用帶數據的請求,創建一個新的訂單)

PUT更新一個資源

http://example.com/api/orders/123

(使用帶數據的請求,更新#123訂單)

DELETE刪除一個資源

http://example.com/api/orders/123

刪除訂單#123

REST請求並不需要特定的數據格式,通常使用JSON作為請求體,或者URL的查詢參數的一部份。

設計一個簡單的web service

下面的任務將會練習設計以REST準則為指引,通過不同的請求方法操作資源,標識資源的例子。

我們將寫一個To Do List 應用,並且設計一個web service。第一步,規劃一個根URL,例如:

http://[hostname]/todo/api/v1.0/

上面的URL包括了應用程式的名稱、API版本,這是十分有用的,既提供了命名空間的劃分,同時又與其它系統區分開來。版本號在升級新特性時十分有用,當一個新功能特性增加在新版本下面時,並不影響舊版本。

第二步,規劃資源的URL,這個例子十分簡單,只有任務清單。

規劃如下:

HTTP方法URI動作GEThttp://[hostname]/todo/api/v1.0/tasks檢索任務清單GEThttp://[hostname]/todo/api/v1.0/tasks/[task_id]檢索一個任務POSThttp://[hostname]/todo/api/v1.0/tasks創建一個新任務PUThttp://[hostname]/todo/api/v1.0/tasks/[task_id]更新一個已存在的任務DELETEhttp://[hostname]/todo/api/v1.0/tasks/[task_id]刪除一個任務

我們定義任務清單有以下欄位:

id:唯一標識。整型。

title:簡短的任務描述。字符串型。

description:完整的任務描述。文本型。

done:任務完成狀態。布爾值型。

以上基本完成了設計部份,接下來我們將會實現它!

 簡單了解Flask框架

Flask好簡單,但是又很強大的Python web 框架。這裡有一系列教程Flask Mega-Tutorial series。(註:Django\Tornado\web.py感覺好多框:()

在我們深入實現web service之前,讓我們來簡單地看一個Flask web 應用的結構示例。

這裡都是在Unix-like(Linux,Mac OS X)作業系統下面的演示,但是其它系統也可以跑,例如windows下的Cygwin。可能命令有些不同吧。(註:忽略Windows吧。)

先使用virtualenv安裝一個Flask的虛擬環境。如果沒有安裝virtualenv,開發python必備,最好去下載安裝。https://pypi.python.org/pypi/virtualenv

$ mkdir todo-api
$ cd todo-api
$ virtualenv flask
New python executable in flask/bin/python
Installing setuptools...done.
Installing pip....done.
$ flask/bin/pip install flask

這樣做好了一個Flask的開發環境,開始創建一個簡單的web應用,在當前目錄裡面創建一個app.py文件:

#!flask/bin/python
from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
return "Hello, World!"

if __name__ == '__main__':
app.run(debug=True)

去執行app.py:

$ chmod a+x app.py
$ ./app.py
* Running on http://127.0.0.1:5000/
* Restarting with reloader

現在可以打開瀏覽器,輸入http://localhost:5000去看看這個Hello,World!

好吧,十分簡單吧。我們開始轉換到RESTful service!

使用Python 和 Flask實現RESTful services

使用Flask建立web services超級簡單。

當然,也有很多Flask extensions可以幫助建立RESTful services,但是這個例實在太簡單了,不需要使用任何擴展。

這個web service提供增加,刪除、修改任務清單,所以我們需要將任務清單存儲起來。最簡單的做法就是使用小型的資料庫,但是資料庫並不是本文涉及太多的。可以參考原文作者的完整教程。Flask Mega-Tutorial series

在這裡例子我們將任務清單存儲在內存中,這樣只能運行在單進程和單線程中,這樣是不適合作為生產伺服器的,若非就必需使用資料庫了。

現在我們準備實現第一個web service的入口點:

#!flask/bin/python

from flask import Flask, jsonify

app = Flask(__name__)

tasks = [
{
'id': 1,
'title': u'Buy groceries',
'description': u'Milk, Cheese, Pizza, Fruit, Tylenol',
'done': False
   },
{
'id': 2,
'title': u'Learn Python',
'description': u'Need to find a good Python tutorial on the web',
'done': False
   }
]

@app.route('/todo/api/v1.0/tasks', methods=['GET'])
def get_tasks():
return jsonify({'tasks': tasks})

if __name__ == '__main__':
app.run(debug=True)

正如您所見,並沒有改變太多代碼。我們將任務清單存儲在list內(內存),list存放兩個非常簡單的數組字典。每個實體就是我們上面定義的欄位。

而 index 入口點有一個get_tasks函數與/todo/api/v1.0/tasks URI關聯,只接受http的GET方法。

這個響應並非一般文本,是JSON格式的數據,是經過Flask框架的 jsonify模塊格式化過的數據。

使用瀏覽器去測試web service並不是一個好的辦法,因為要創建不同類弄的HTTP請求,事實上,我們將使用curl命令行。如果沒有安裝curl,快點去安裝一個。

像剛才一樣運行app.py。

打開一個終端運行以下命令:

$ curl -i http://localhost:5000/todo/api/v1.0/tasks
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 294
Server: Werkzeug/0.8.3 Python/2.7.3
Date: Mon, 20 May 2013 04:53:53 GMT

{
"tasks": [
{
"description": "Milk, Cheese, Pizza, Fruit, Tylenol",
"done": false,
"id": 1,
"title": "Buy groceries"
   },
{
"description": "Need to find a good Python tutorial on the web",
"done": false,
"id": 2,
"title": "Learn Python"
   }
]
}


這樣就調用了一個RESTful service方法!

現在,我們寫第二個版本的GET方法獲取特定的任務。獲取單個任務:


from flask import abort

@app.route('/todo/api/v1.0/tasks/<int:task_id>', methods=['GET'])
def get_task(task_id):
task = filter(lambda t: t['id'] == task_id, tasks)
if len(task) == 0:
abort(404)
return jsonify({'task': task[0]})

第二個函數稍稍複雜了一些。任務的id包含在URL內,Flask將task_id參數傳入了函數內。

通過參數,檢索tasks數組。如果參數傳過來的id不存在於數組內,我們需要返回錯誤代碼404,按照HTTP的規定,404意味著是"Resource Not Found",資源未找到。

如果找到任務在內存數組內,我們通過jsonify模塊將字典打包成JSON格式,並發送響應到客戶端上。就像處理一個實體字典一樣。

試試使用curl調用:

$ curl -i http://localhost:5000/todo/api/v1.0/tasks/2
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 151
Server: Werkzeug/0.8.3 Python/2.7.3
Date: Mon, 20 May 2013 05:21:50 GMT

{
"task": {
"description": "Need to find a good Python tutorial on the web",
"done": false,
"id": 2,
"title": "Learn Python"
 }
}
$ curl -i http://localhost:5000/todo/api/v1.0/tasks/3
HTTP/1.0 404 NOT FOUND
Content-Type: text/html
Content-Length: 238
Server: Werkzeug/0.8.3 Python/2.7.3
Date: Mon, 20 May 2013 05:21:52 GMT

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>404 Not Found</title>
<h1>Not Found</h1>
<p>The requested URL was not found on the server.</p><p>If you entered the URL manually please check your spelling and try again.</p>

當我們請求#2 id的資源時,可以獲取,但是當我們請求#3的資源時返回了404錯誤。並且返回了一段奇怪的HTML錯誤,而不是我們期望的JSON,這是因為Flask產生了默認的404響應。客戶端需要收到的都是JSON的響應,因此我們需要改進404錯誤處理:


from flask import make_response

@app.errorhandler(404)
def not_found(error):
return make_response(jsonify({'error': 'Not found'}), 404)

這樣我們就得到了友好的API錯誤響應:


$ curl -i http://localhost:5000/todo/api/v1.0/tasks/3
HTTP/1.0 404 NOT FOUND
Content-Type: application/json
Content-Length: 26
Server: Werkzeug/0.8.3 Python/2.7.3
Date: Mon, 20 May 2013 05:36:54 GMT

{
"error": "Not found"
}

接下來我們實現 POST 方法,插入一個新的任務到數組中:

from flask import request

@app.route('/todo/api/v1.0/tasks', methods=['POST'])
def create_task():
if not request.json or not 'title' in request.json:
abort(400)
task = {
'id': tasks[-1]['id'] + 1,
'title': request.json['title'],
'description': request.json.get('description', ""),
'done': False
   }
tasks.append(task)
return jsonify({'task': task}), 201

request.json裡面包含請求數據,如果不是JSON或者裡面沒有包括title欄位,將會返回400的錯誤代碼。

當創建一個新的任務字典,使用最後一個任務id數值加1作為新的任務id(最簡單的方法產生一個唯一欄位)。這裡允許不帶description欄位,默認將done欄位值為False。

將新任務附加到tasks數組裡面,並且返回客戶端201狀態碼和剛剛添加的任務內容。HTTP定義了201狀態碼為「Created」。

測試上面的新功能:

$ curl -i -H "Content-Type: application/json" -X POST -d '{"title":"Read a book"}' http://localhost:5000/todo/api/v1.0/tasks
HTTP/1.0 201 Created
Content-Type: application/json
Content-Length: 104
Server: Werkzeug/0.8.3 Python/2.7.3
Date: Mon, 20 May 2013 05:56:21 GMT

{
"task": {
"description": "",
"done": false,
"id": 3,
"title": "Read a book"
 }
}

注意:如果使用原生版本的curl命令行提示符,上面的命令會正確執行。

全部請閱讀原文

新書(Pdf/Kindle版)[複製下面文字,打開手機淘寶]:

【數據分析俠  《人人都會數據分析》20萬字書籍】http://m.tb.cn/h.AJEkoq 點擊連結,再選擇瀏覽器打開;或複製這條信息¥fSnh09F0Vpy¥後打開👉手淘👈

相關焦點

  • 10分鐘,帶你用Python構建RESTful API 服務
    Hello World首先,我們使用 Pycharm 創建一個 Flask Web 項目,初始化代碼如下:from flask import Flaskapp = Flask(__name__)@app.route('/')def hello_world():    return 'Hello World!'
  • 教你 10 分鐘構建一套 RESTful API 服務( 中 )
    Hello World首先,我們使用 Pycharm 創建一個 Flask Web 項目,初始化代碼如下:from flask import Flaskapp = Flask(__name__)@app.route('/')def hello_world():    return 'Hello World!'
  • Python Flask API實現方法-測試開發【提測平臺】階段小結(一)
    Flask 一個python的web架構服務,實現前後端的開發,在本項目主要是使用它的Resful API實現能能力,雖說頁面能力可以通過jinjia實現,但當今有更簡單,好用的類似vue這樣的開箱即用的開源框架,因此做到前後端分離,讓它發揮好後端接口能力就好了,當然還有一些其他優秀的框架比如tornado、django
  • 數據分析36計(28):Python 使用 Flask+Docker, 100行代碼內實現機器學習實時預測​
    本文的想法是快速輕鬆地構建 Docker 容器,Python 以使用 Flask 實現機器學習模型執行在線預測 API 。我們將使用 Docker 和 Flask-RESTful 實現線性判別分析和多層感知器神經網絡模型的實時預測。
  • docker系列學習(二):Docker + Flask 例子
    在接下來的學習中,你將學習到如何創建,運行,構建,推送,拉取,殺死,修剪和使用 flask 作為 api 在 docker 中如何工作。設置步驟創建一個文件夾來保存項目。我們將在這裡花費大部分時間,首先我們使用 mkdir 命令創建文件夾。mkdir hello_docker_flask之後利用 cd 命令切換到這個目錄。
  • [譯] 使用 Python Flask 框架發布機器學習 API
    >原文地址:Publishing Machine Learning API with Python Flask原文作者:Andrejus Baranovskis譯文出自:掘金翻譯計劃本文永久連結:https://github.com/xitu/gold-miner/blob/master/TODO1/publishing-machine-learning-api-with-python-flask.md
  • Python實戰 | 基於 Flask 部署 Keras 深度學習模型
    2.4 web 開發框架——Flask之前學習 python 語言,從來沒有關注過Web開發這一章節,因為工作內容並沒有涉及這一部分。如今需要重新看一下。早期軟體主要運行在桌面上,資料庫這樣的軟體運行在伺服器端,這種Client/Server模式簡稱CS架構。
  • API測試指南
    HTTP是一個無狀態的協議,但是在網際網路的產品形態中,一個用戶登錄系統成功後,需要記錄下誰登錄了這個系統,以及這個用戶它其他的數據信息,這就需要很清楚的掌握COOKIE的請求流程,當然這中間有這麼幾點是需要清楚的知道的,分別是COOKIE的請求流程,SESSION的請求流程,TOKEN的請求流程,以及HTTPS的請求流程,當然了還有我們經常面試被問到的請求方法,如GET,METHOD請求方法,案例剛才案例說的
  • 基於《Flask Web開發:基於Python的Web應用開發實戰》最全總結
    • Markdown: 使用Python實現的伺服器端Markdown到HTML的轉換程序。• Bleach: 使用Python實現的HTML清理器。安裝適用於生產環境的Web伺服器,例如Gunicorn或uWSGI。 為了啟用安全HTTP,購買、安裝並配置SSL證書。 (可選,但強烈推薦)安裝前端反向代理伺服器,例如nginx或Apache。反向代理伺服器能直接服務於靜態文件,而把其他請求轉發給程序使用的Web伺服器。Web伺服器監聽localhost中的一個私有埠。
  • 如何使用MongoDB和Docker運行Flask應用
    使用Docker Compose提供了在運行多個Docker容器運行命令時的易用性。它允許你在一個單獨的Compose文件裡定義你所有的服務,並且你可以只用一條命令實現從配置文件創建並運行所有的服務。這保證在容器結構中貫穿著版本控制。Docker Compose使用項目名來實現環境的相互隔離,這允許你在一個主機上運行多個環境。
  • 後端開發必備的 RestFul API 知識
    相關閱讀:•http://www.ruanyifeng.com/blog/2014/05/restful_api.html(阮一峰,這篇文章大部分內容來源)•https://www.baeldung.com/spring-hateoas-tutorial(RestFul API Tutorial)•https://aisensiy.github.io/2017/06/04
  • Vue + Flask 實戰開發系列(一)
    我更喜歡從前端開始,因為項目結構比後端複雜得多。在這個系列中,我使用vue-cli命令行開發工具創建了一個簡單的Vue項目:$ vue create vue-flask-app$ cd vue-flask-app通過上面的的命令,我們的Vue前端項目就創建成功了。
  • 基於 Flask 部署 Keras 深度學習模型
    2.4 web 開發框架——Flask之前學習 python 語言,從來沒有關注過Web開發這一章節,因為工作內容並沒有涉及這一部分。如今需要重新看一下。早期軟體主要運行在桌面上,資料庫這樣的軟體運行在伺服器端,這種Client/Server模式簡稱CS架構。
  • Python Web實戰:Flask + Vue 開發一個漂亮的詞雲網站
    這是一個前端用 Vue,後端用 Python 的 Web 框架 Flask 開發的詞雲生成應用,代碼已上傳到 flask-vue-word-cloud項目地址:https://github.com/77Y/flask-vue-word-cloud
  • RESTful API 最佳實踐(阮一峰)
    這時,客戶端發出的 HTTP 請求,要加上X-HTTP-Method-Override屬性,告訴伺服器應該使用哪一個動詞,覆蓋POST方法。這沒有統一的規定,但是常見的操作是讀取一個集合,比如GET /articles(讀取所有文章),這裡明顯應該是複數。為了統一起見,建議都使用複數 URL,比如GET /articles/2要好於GET /article/2。
  • Flask 偏函數、g對象、flask-session、資料庫連接池、信號、自製命令、flask-admin
    連結資料庫資料庫連接池版utils/sql.py五、信號六、命令 flask-script七、flask-admin安裝簡單使用將表模型註冊到 admin 中如果有個欄位是圖片指端當函數的參數個數太多,需要簡化時,使用 functools.partial 可以創建一個新的函數
  • RESTful API 設計規範
    為了更好的討論規範帶來的爭議及問題,現已把該文檔整理並開源到 github (https://github.com/godruoyi/restful-api-specification),關於大家補充及提 issue。
  • (收藏)哪些 Python 庫讓你相見恨晚?
    Flaskflask-api – 為 flask 開發的,可瀏覽 Web APIs 。flask-restful – 為 flask 快速創建REST APIs 。flask-restless – 為 SQLAlchemy 定義的資料庫模型創建 RESTful APIs 。
  • 20分鐘理解並寫出簡易的網速監控API
    當然,你也可以用正則表達式來實現。畢竟是自己使用的簡易API,如果不是特別在意的話,實現方法不優雅也無妨。至此我們就能把自己需要的信息提取出來了。2 熟悉 flask 框架Flask是一個使用Python編寫的輕量級Web應用框架。基於Werkzeug WSGI工具箱和Jinja2 模板引擎。 Flask使用BSD授權。
  • 從頭搭建一個flask鑑權系統之登陸
    >本文涉及到如下知識點1. flask-login的簡單使用2.GitHub鑑權登陸實踐,flask-github使用4.創建好這個OAuth程序後,我們就會獲得Client ID(客戶端ID)和Client Secret(客戶端密鑰),在後面調用Github的API時使用。04. 本地鑑權根據剛才的表結構設計,對於本地鑑權,可以在models.py文件中創建一個WebUser類,定義對應的資料庫欄位。