Python Web 框架之FastAPI

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

如果我們使用 Flask 來開發(fā)這個接口,那么代碼是這樣的:

from flask import Flask, request

app = Flask(__name__)


@app.route('/insert', methods=['POST'])
def insert():
    info = request.json
    print(info,type(info))
    name = info['name']
    age = info['age']
    age_after_10_years = age + 10
    msg = '此人名叫:{},10年后,此人年齡:{}'.format(name, age_after_10_years)
    return str({'success': True, 'msg': msg})

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

代碼看起來已經(jīng)很簡潔了。我們用requests發(fā)個請求看看效果,如下圖所示:

看起來沒什么問題。
現(xiàn)在,我搞點破壞,把age字段改成字符串,再運行一下:
不出所料,報錯了。

現(xiàn)在我們把age字段改回數(shù)字,但是直接移除name字段:

又報錯了。

為了防止用戶不按規(guī)矩提交數(shù)據(jù),我們必須在接口里面做好各種異常數(shù)據(jù)的判斷。于是增加判斷以后的代碼變得復(fù)雜了:

from flask import Flask, request

app = Flask(__name__)

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


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

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

下面我們來看一下,現(xiàn)代化的 web 框架:FastApi能把這個工程簡化到什么程度:

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}

我們還是使用 requests 發(fā)一條信息給 FastApi 開發(fā)的 HTTP 接口。對于正常數(shù)據(jù),正常使用:

現(xiàn)在我們把age字段改成字符串:

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

我們再試一試把name字段去掉:

返回友好信息,提示值錯誤:name字段丟失

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

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

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

使用pip或者pipenv即可安裝 FastApi:

pip install fastapi
pipenv install fastapi

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

from fastapi import FastAPI

app = FastAPI()


@app.get('/')
def index():
    return {'message': '你已經(jīng)正確創(chuàng)建 FastApi 服務(wù)!'}

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

寫好代碼以后,我們需要使用uvicorn來運行 FastApi。首先使用pip或者pipenv安裝uvicorn

pip install uvicorn
pipenv install uvicorn

然后執(zhí)行命令:

uvicorn main:app --reload

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

運行命令以后,我們訪問http://127.0.0.1:8000可以看到接口已經(jīng)正確返回了 JSON 格式的數(shù)據(jù):

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

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

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

如果想限定 uid 只能是數(shù)字,不能是字符串怎么辦呢?你只需要多加 4 個字符

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

對函數(shù)query的參數(shù)使用類型標注,標注為 int 類型?,F(xiàn)在我們再來訪問一下接口:

當 query 后面的參數(shù)不是整數(shù)時,正常報錯了。

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

但使用 FastApi 的時候,我們只需要類型標注就能解決所有問題。首先我們導(dǎo)入from pydantic import BaseModel,然后繼承BaseModel實現(xiàn)我們允許 POST 方法提交上來的數(shù)據(jù)字段和格式:

from pydantic import BaseModel

app = FastAPI()


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

People這個類通過類型標注,指定了它里面的 4 個字段和他們的類型?,F(xiàn)在,我們來實現(xiàn) POST 方法:

@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}

insert函數(shù)的參數(shù)people通過類型標注指定為People類型。

當我們使用 POST 方式提交數(shù)據(jù)時,F(xiàn)astApi 自動會以People中定義的字段為基準來校驗數(shù)據(jù),發(fā)現(xiàn)不對就返回報錯信息。

除了開發(fā)接口變得非常簡單外,F(xiàn)astApi 還會自動幫我們生成接口文檔。大家訪問http://127.0.0.1:8000/docs,可以看到接口文檔已經(jīng)自動生成好了:

這個接口不僅能看,而且直接就能在接口頁面修改樣例數(shù)據(jù),發(fā)送請求,現(xiàn)場測試:

以上是對 FastApi 的極簡介紹。有興趣的同學(xué)可以查閱它的官方文檔。

最后,告訴大家,F(xiàn)astApi 是一個異步 Web 框架,它的速度非常非常非常快。遠遠超過 Flask。

FastApi 是最快的幾個 Web 框架之一。速度可以匹敵 Golang 寫的接口。詳細的對比可以看:https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7

學(xué)習(xí)來源

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容