Python web框架FastAPI入門(mén)——一個(gè)比Flask和Tornada更高性能的API 框架

用官方的話來(lái)說(shuō),F(xiàn)astAPI 是一種現(xiàn)代,快速(高性能)的 Web 框架,基于標(biāo)準(zhǔn)Python 類型提示使用 Python 3.6+ 構(gòu)建 API

FastAPI 站在巨人的肩膀上?

很大程度上來(lái)說(shuō),這個(gè)巨人就是指 Flask 框架。

FastAPI 從語(yǔ)法上和 Flask 非常的相似,有異曲同工之妙。

技術(shù)背景:Py3.6+,Starlette,Pydantic

其實(shí)不僅僅是 FastAPI ,就連 Sanic 也是基于 Flask 快速開(kāi)發(fā)的 Web API 框架。

廢話少說(shuō),代碼總是能給人帶來(lái)愉悅感 (抱頭),直接開(kāi)懟。

安裝

pip install fastapi 
pip install uvicorn

創(chuàng)建一個(gè) main.py 文件

from fastapi import FastAPIapp = FastAPI() # 創(chuàng)建 api 對(duì)象
@app.get("/") # 根路由def root():   
 return {"武漢": "加油?。?!"}
@app.get("/say/{data}")def say(data: str,q: int):    
return {"data": data, "item": q}

上面搭建了一個(gè)最簡(jiǎn)單的 FastAPI 應(yīng)用,看起來(lái)和 Flask 完全一樣,莫名的喜感。

使用以下命令來(lái)啟動(dòng)服務(wù)器:

uvicorn main:app --reload

FastAPI 推薦使用 uvicorn 來(lái)運(yùn)行服務(wù),Uvicorn 是基于uvloop 和 httptools 構(gòu)建的閃電般快速的 ASGI 服務(wù)器。

uvicorn main:app 指的是:

main:文件main.py

app:  創(chuàng)建的啟用對(duì)象

--reload:  熱啟動(dòng),方便代碼的開(kāi)發(fā)

啟動(dòng)界面如下:

INFO 信息告訴我們已經(jīng)監(jiān)聽(tīng)了本地的 8000 端口,訪問(wèn) http://127.0.0.1:8000 得到結(jié)果

傳入?yún)?shù)

再來(lái)看看 FastAPI 的異步代碼

from fastapi import FastAPIapp = FastAPI() # 創(chuàng)建 api 對(duì)象
@app.get("/") # 根路由async def root():    
return {"武漢": "加油?。。?}
@app.get("/say/{data}")async def say(data: str,q: int = None):   
 return {"data": data, "q": q}

開(kāi)啟服務(wù)后訪問(wèn)結(jié)果是一樣的。

在上面的路由方法中,我們傳入了一個(gè) q 參數(shù)并且初始為 None,如果不給默認(rèn)值,并且不傳參,代碼將直接報(bào)錯(cuò)。

來(lái)看看 FastAPI 是如何處理錯(cuò)誤的:


可以看到,即使是報(bào)錯(cuò),也是優(yōu)美的輸入一個(gè)帶有錯(cuò)誤字段的 JSON,這就非常的友好了,這也是體現(xiàn)了 FastAPI 減少更多的人為錯(cuò)誤的特性,返回也更加的簡(jiǎn)潔直觀。

在命令行輸出:

再來(lái)看看 FastAPI 的交互文檔

根據(jù)官方文檔,打開(kāi) http://127.0.0.1:8000/docs

看到:

支持動(dòng)態(tài)傳入數(shù)據(jù):


結(jié)果:

從交互體驗(yàn)上也是無(wú)比的友好,讓代碼在生產(chǎn)中更加健壯。

現(xiàn)在我們算是快速的體驗(yàn)了一波 FastAPI 騷操作,從代碼上和 Flask 及其的類似,體驗(yàn)性更好。

那么再來(lái)看看最新的 Python web框架的性能響應(yīng)排行版

從并發(fā)性上來(lái)說(shuō)是完全碾壓了 Flask (實(shí)際上也領(lǐng)先了同為異步框架的tornado 不少),看來(lái) FastAPI 也真不是蓋的,名副其實(shí)的高性能 API 框架呀!

查詢參數(shù)

先來(lái)看看官方小 demo

from fastapi import FastAPI
app = FastAPI()fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
@app.get("/items/")
async def read_item(skip: int = 0, limit: int = 10):    
return fake_items_db[skip : skip + limit]

該查詢是 ? URL中位于關(guān)鍵字之后的一組鍵值對(duì),以&字符分隔。

在 url 中進(jìn)行查詢

http://127.0.0.1:8000/items/?skip=0&limit=10

skip:查詢的起始參數(shù)

limit:查詢的結(jié)束參數(shù)

成功返回查詢列表。

查詢參數(shù)類型轉(zhuǎn)換

FastAPI 非常聰明,足以辨別 路徑參數(shù) 和 查詢參數(shù)。

來(lái)看看具體的例子:

from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: str, q: str = None, short: bool = False):    
item = {"item_id": item_id}   
 if q:        
item.update({"q": q})    
if not short:        
item.update(           
 {"description": "This is an amazing item that has a long description"}        
)    
return item

看看其訪問(wèn)路徑,執(zhí)行以下的任何一種 url 訪問(wèn)方式

http://127.0.0.1:8000/items/武漢加油?short=1

http://127.0.0.1:8000/items/武漢加油?short=True

http://127.0.0.1:8000/items/武漢加油?short=true

http://127.0.0.1:8000/items/武漢加油?short=on

http://127.0.0.1:8000/items/武漢加油?short=yes

可以發(fā)現(xiàn)任何大小寫(xiě)的字母等都會(huì)被轉(zhuǎn)換成 bool 值的參數(shù) True,這就是所謂模糊驗(yàn)證參數(shù),對(duì)于開(kāi)發(fā)者來(lái)說(shuō)這是個(gè)好消息。

要知道的是,如果 short 參數(shù)沒(méi)有默認(rèn)值,則必須傳參,否則 FastAPI 將會(huì)返回類似以下的錯(cuò)誤信息。

{    
    "detail": [        
    {            
    "loc": [                
    "query",                
    "needy"            
],           
     "msg": "field required",            
    "type": "value_error.missing"       
     }    
]}

創(chuàng)建數(shù)據(jù)模型

前面說(shuō)到 FastAPI 依賴 Pydantic 模塊,所以首先,你需要導(dǎo)入 Pydantic 的 BaseModel 類。

from fastapi import FastAPI
from pydantic import BaseModel
# 請(qǐng)求主體類
class Item(BaseModel):    
name: str = "武漢加油 ??!"    
description: str = None    
price: float = 233   
tax: float = Noneapp = FastAPI()
@app.post("/items/")
async def create_item(item: Item):    
return item

發(fā)送 post 請(qǐng)求來(lái)提交一個(gè) Item(請(qǐng)求主體) 并返回,來(lái)看看提交過(guò)程。


成功提交并返回 200 狀態(tài)碼

請(qǐng)求主體+路徑+查詢參數(shù),在請(qǐng)求主體的基礎(chǔ)上加入 url 動(dòng)態(tài)路徑參數(shù) 和 查詢參數(shù)

from fastapi import FastAPI
from pydantic import BaseModelclass 

Item(BaseModel):    
name: str    
description: str = None   
 price: float   
 tax: float = Noneapp = FastAPI()
@app.put("/items/{item_id}")
async def create_item(item_id: int, item: Item, q: str = None):    
result = {"item_id": item_id, **item.dict()}   
 if q:       
 result.update({"q": q})   
 return result

put 方法用于更新,傳入?yún)?shù)后成功返回一個(gè)字典。

關(guān)于模板引擎

FastAPI 不像 Flask 那樣自帶 模板引擎(Jinja2),也就是說(shuō)沒(méi)有默認(rèn)的模板引擎,從另一個(gè)角度上說(shuō),F(xiàn)astAPI 在模板引擎的選擇上變得更加靈活,極度舒適。

以 Jinja2 模板為例

安裝依賴

pip install jinja2
pip install aiofiles # 用于 fastapi 的異步靜態(tài)文件

具體的用法

# -*- coding:utf-8 -*-
from fastapi import FastAPI, Request
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
import uvicorn
app = FastAPI()app.mount("/static", StaticFiles(directory="static"), name="static") # 掛載靜態(tài)文件,指定目錄templates = Jinja2Templates(directory="templates") # 模板目錄@app.get("/data/{data}")
async def read_data(request: Request, data: str):   
 return templates.TemplateResponse("index.html", {"request": request, "data": data})

if __name__ == '__main__':    
uvicorn.run(app, host="127.0.0.1", port=8000)

html 文件渲染

<html>
<head>    
<title>武漢加油</title>
</head>
<body>   
 <h1>高呼: {{ data }}</h1>
</body>
</html>

在瀏覽器鍵入 http://127.0.0.1:8000/data/武漢加油

值得注意的是,在返回的 TemplateRespone 響應(yīng)時(shí),必須帶上 request 的上下文對(duì)象,傳入?yún)?shù)放在同一字典。

這樣一來(lái),又可以像 Flask 一樣的使用熟悉的 Jinja2 了,哈哈。

做個(gè)小總結(jié)的話就是 FastAPI 在用法上也是及其簡(jiǎn)單,速度更快,性能更好,容錯(cuò)率更高,整體上更牛逼。但是我在設(shè)想如此之快的框架,畢竟發(fā)布的時(shí)間不長(zhǎng),缺少像 Flask 框架的第三方庫(kù)和各種插件,所以要想真正意義上替代還是需要一定的時(shí)間。

FastAPI 的官方文檔有詳細(xì)的介紹和實(shí)例,入門(mén)篇到此結(jié)束。

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

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

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