用它5分鐘以後,我放棄用了四年的 Flask

優質文章,第一時間送達!

用它5分钟以后,我放弃用了四年的 Flask

有一個非常簡單的需求:編寫一個 HTTP 接口,使用 POST 方式發送一個 JSON 字符串,接口裡面讀取發送上來的參數,對其中某個參數進行處理,並返回。

如果我們使用 Flask 來開發這個接口,那麼代碼是這樣的:

<code>from flask import Flask, request

app = Flask(__name__)


@app.route('/insert', methods=['POST'])
def insert:
info = request.json
name = info['name']
age = info['age']
age_after_10_years = age + 10
msg = f'此人名叫:{name},10年後,此人年齡:{age_after_10_years}'
return {'success': True, 'msg': msg}
/<code>

代碼看起來已經很簡潔了。我們用<code>requests/<code>發個請求看看效果,如下圖所示:

用它5分钟以后,我放弃用了四年的 Flask

看起來沒什麼問題。

現在,我搞點破壞,把<code>age/<code>字段改成字符串,再運行一下:

用它5分钟以后,我放弃用了四年的 Flask

不出所料,報錯了。

現在我們把<code>age/<code>字段改回數字,但是直接移除<code>name/<code>字段:

用它5分钟以后,我放弃用了四年的 Flask

又報錯了。

為了防止用戶不按規矩提交數據,我們必須在接口裡面做好各種異常數據的判斷。於是增加判斷以後的代碼變得複雜了:

<code>@app.route('/insert', methods=['POST'])
def insert:
info = request.json
name = info.get('name', '')
if not name:
return {'success': False, 'msg': 'name 參數不可省略,不可為空!'}
age = info.get('age', 0)
if not isinstance(age, int):
return {'success': False, 'msg': 'age參數不是數字!'}
age_after_10_years = age + 10
msg = f'此人名叫:{name},10年後,此人年齡:{age_after_10_years}'
return {'success': True, 'msg': msg}
/<code>

看來,用 Flask,雖然能讓你用很短的代碼寫出一個能工作的項目。但要寫成一個可以正常使用的項目,還是需要你自己寫更多代碼。

下面我們來看一下,現代化的 web 框架:<code>FastApi/<code>能把這個工程簡化到什麼程度:

<code>from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI


class People(BaseModel):
name: str
age: int
address: str
salary: float


@app.post('/insert')
def insert(people: People):
age_after_10_years = people.age + 10
msg = f'此人名字叫做:{people.name},十年後此人年齡:{age_after_10_years}'
return {'success': True, 'msg': msg}
/<code>

我們還是使用 requests 發一條信息給 FastApi 開發的 HTTP 接口。對於正常數據,正常使用:

用它5分钟以后,我放弃用了四年的 Flask

現在我們把<code>age/<code>字段改成字符串:

用它5分钟以后,我放弃用了四年的 Flask

返回友好的提示信息,告訴我<code>類型錯誤:age 字段不是 integer/<code>。

我們再試一試把<code>name/<code>字段去掉:

用它5分钟以后,我放弃用了四年的 Flask

返回友好信息,提示<code>值錯誤:name字段丟失/<code>。

整個過程中,對類型的檢查全都由 FastApi 自己完成。我們省下來很多時間。

我用了 Flask 四年,但在使用了 5 分鐘 FastApi 以後,我決定以後不再使用 Flask 了。

回過頭來,我們好好介紹一下 FastApi。

使用<code>pip/<code>或者<code>pipenv/<code>即可安裝 FastApi:

<code>pip install fastapi
pipenv install fastapi
/<code>

安裝完成以後,我們來完成第一個 API:

<code>from fastapi import FastAPI

app = FastAPI


@app.get('/')
def index:
return {'message': '你已經正確創建 FastApi 服務!'}
/<code>

這裡的寫法跟 Flask 幾乎一致。只不過在 Flask 中,我們定義路由的裝飾器為<code>@app.route('/')/<code>。而這裡寫為<code>@app.get('/')/<code>

如下圖所示:

用它5分钟以后,我放弃用了四年的 Flask

寫好代碼以後,我們需要使用<code>uvicorn/<code>來運行 FastApi。首先使用<code>pip/<code>或者<code>pipenv/<code>安裝<code>uvicorn/<code>:

<code>pip install uvicorn
pipenv install uvicorn
/<code>

然後執行命令:

<code>uvicorn main:app --reload
/<code>

其中<code>main/<code>表示我們的代碼文件為<code>main.py/<code>,<code>app/<code>表示我們初始化的 FastApi 對象的名字。<code>--reload/<code>參數表示在修改了代碼以後立即生效,不需要重啟。

運行命令以後,我們訪問<code>http://127.0.0.1:8000/<code>可以看到接口已經正確返回了 JSON 格式的數據:

用它5分钟以后,我放弃用了四年的 Flask

那麼如何定義一個帶參數的 GET 方法呢?我們再寫一段代碼:

<code>@app.get('/query/{uid}')
def query(uid):
msg = f'你查詢的 uid 為:{uid}'
return {'success': True, 'msg': msg}
/<code>

寫好代碼以後,我們直接在瀏覽器裡面訪問新的地址,可以看到修改已經生效了,如下圖所示:

用它5分钟以后,我放弃用了四年的 Flask

如果想限定 uid 只能是數字,不能是字符串怎麼辦呢?你只需要多加 4 個<code>字符/<code>:

<code>@app.get('/query/{uid}')
def query(uid: int):

msg = f'你查詢的 uid 為:{uid}'
return {'success': True, 'msg': msg}
/<code>

對函數<code>query/<code>的參數使用類型標註,標註為 int 類型。現在我們再來訪問一下接口:

用它5分钟以后,我放弃用了四年的 Flask

當 query 後面的參數不是整數時,正常報錯了。

我們再來看一下本文一開始的 POST 方法。在使用 Flask 的時候,我們需要手動驗證用戶 POST 提交上來的數據是什麼格式的,字段對不對。

但使用 FastApi 的時候,我們只需要類型標註就能解決所有問題。首先我們導入<code>from pydantic import BaseModel/<code>,然後繼承<code>BaseModel/<code>實現我們允許 POST 方法提交上來的數據字段和格式:

<code>from pydantic import BaseModel

app = FastAPI


class People(BaseModel):
name: str
age: int
address: str
salary: float
/<code>

<code>People/<code>這個類通過類型標註,指定了它裡面的 4 個字段和他們的類型。現在,我們來實現 POST 方法:

<code>@app.post('/insert')
def insert(people: People):
age_after_10_years = people.age + 10
msg = f'此人名字叫做:{people.name},十年後此人年齡:{age_after_10_years}'
return {'success': True, 'msg': msg}
/<code>

<code>insert/<code>函數的參數<code>people/<code>通過類型標註指定為<code>People/<code>類型。

當我們使用 POST 方式提交數據時,FastApi 自動會以<code>People/<code>中定義的字段為基準來校驗數據,發現不對就返回報錯信息。

除了開發接口變得非常簡單外,FastApi 還會自動幫我們生成接口文檔。大家訪問<code>http://127.0.0.1:8000/docs/<code>,可以看到接口文檔已經自動生成好了:

用它5分钟以后,我放弃用了四年的 Flask

這個接口不僅能看,而且直接就能在接口頁面修改樣例數據,發送請求,現場測試:

用它5分钟以后,我放弃用了四年的 Flask

以上是對 FastApi 的極簡介紹。有興趣的同學可以查閱它的官方文檔[1]

最後,告訴大家,FastApi 是一個異步 Web 框架,它的速度非常非常非常快。遠遠超過 Flask。

用它5分钟以后,我放弃用了四年的 Flask

FastApi 是最快的幾個 Web 框架之一。速度可以匹敵 Golang 寫的接口。詳細的對比可以看:one of the fastest Python frameworks available[2]


分享到:


相關文章: