(入門篇)簡析一個比Flask和Tornado更高性能的API 框架FastAPI(adapter框架)
(入門篇)簡析一個比Flask和Tornado更高性能的API 框架FastAPI(adapter框架)
用官方的話來說,F(xiàn)astAPI 是一種現(xiàn)代,快速(高性能)的 Web 框架,基于標(biāo)準(zhǔn)Python 類型提示使用 Python 3.6 構(gòu)建 api
FastAPI 站在巨人的肩膀上?
很大程度上來說,這個巨人就是指 Flask 框架。
FastAPI 從語法上和 Flask 非常的相似,有異曲同工之妙。
技術(shù)背景:Py3.6 ,Starlette,Pydantic
其實(shí)不僅僅是 FastAPI ,就連 Sanic 也是基于 Flask 快速開發(fā)的 Web API 框架。
廢話少說,代碼總是能給人帶來愉悅感 (抱頭),直接開懟。
安裝
pip install fastapi pip install uvicorn
創(chuàng)建一個 main.py 文件
from fastapi import FastAPIapp = FastAPI() # 創(chuàng)建 api 對象@app.get("/") # 根路由def root(): return {"武漢": "加油!??!"}@app.get("/say/{data}")def say(data: str,q: int): return {"data": data, "item": q}
上面搭建了一個最簡單的 FastAPI 應(yīng)用,看起來和 Flask 完全一樣,莫名的喜感。
使用以下命令來啟動服務(wù)器:
uvicorn main:app --reload
FastAPI 推薦使用 uvicorn 來運(yùn)行服務(wù),Uvicorn 是基于uvloop 和 httptools 構(gòu)建的閃電般快速的 ASGI 服務(wù)器。
uvicorn main:app 指的是:
main:文件main.py
app: 創(chuàng)建的啟用對象
–reload: 熱啟動,方便代碼的開發(fā)
啟動界面如下:
INFO 信息告訴我們已經(jīng)監(jiān)聽了本地的 8000 端口,訪問 http://127.0.0.1:8000 得到結(jié)果
傳入?yún)?shù)
再來看看 FastAPI 的異步代碼
from fastapi import FastAPIapp = FastAPI() # 創(chuàng)建 api 對象@app.get("/") # 根路由async def root(): return {"武漢": "加油?。?!"}@app.get("/say/{data}")async def say(data: str,q: int = None): return {"data": data, "q": q}
開啟服務(wù)后訪問結(jié)果是一樣的。
在上面的路由方法中,我們傳入了一個 q 參數(shù)并且初始為 None,如果不給默認(rèn)值,并且不傳參,代碼將直接報(bào)錯。
來看看 FastAPI 是如何處理錯誤的:
可以看到,即使是報(bào)錯,也是優(yōu)美的輸入一個帶有錯誤字段的 JSON,這就非常的友好了,這也是體現(xiàn)了 FastAPI 減少更多的人為錯誤的特性,返回也更加的簡潔直觀。
在命令行輸出:
再來看看 FastAPI 的交互文檔
根據(jù)官方文檔,打開 http://127.0.0.1:8000/docs
看到:
支持動態(tài)傳入數(shù)據(jù):
結(jié)果:
從交互體驗(yàn)上也是無比的友好,讓代碼在生產(chǎn)中更加健壯。
現(xiàn)在我們算是快速的體驗(yàn)了一波 FastAPI 騷操作,從代碼上和 Flask 及其的類似,體驗(yàn)性更好。
那么再來看看最新的 Python web框架的性能響應(yīng)排行版
從并發(fā)性上來說是完全碾壓了 Flask (實(shí)際上也領(lǐng)先了同為異步框架的tornado 不少),看來 FastAPI 也真不是蓋的,名副其實(shí)的高性能 API 框架呀!
查詢參數(shù)
先來看看官方小 demo
from fastapi import FastAPIapp = 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)鍵字之后的一組鍵值對,以&字符分隔。
在 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ù)。
來看看具體的例子:
from fastapi import FastAPIapp = 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
看看其訪問路徑,執(zhí)行以下的任何一種 url 訪問方式
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)任何大小寫的字母等都會被轉(zhuǎn)換成 bool 值的參數(shù) True,這就是所謂模糊驗(yàn)證參數(shù),對于開發(fā)者來說這是個好消息。
要知道的是,如果 short 參數(shù)沒有默認(rèn)值,則必須傳參,否則 FastAPI 將會返回類似以下的錯誤信息。
{ "detail": [ { "loc": [ "query", "needy" ], "msg": "field required", "type": "value_error.missing" } ]}
創(chuàng)建數(shù)據(jù)模型
前面說到 FastAPI 依賴 Pydantic 模塊,所以首先,你需要導(dǎo)入 Pydantic 的 BaseModel 類。
from fastapi import FastAPIfrom pydantic import BaseModel# 請求主體類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 請求來提交一個 Item(請求主體) 并返回,來看看提交過程。
成功提交并返回 200 狀態(tài)碼
請求主體 路徑 查詢參數(shù),在請求主體的基礎(chǔ)上加入 url 動態(tài)路徑參數(shù) 和 查詢參數(shù)
from fastapi import FastAPIfrom 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ù)后成功返回一個字典。
關(guān)于模板引擎
FastAPI 不像 Flask 那樣自帶 模板引擎(Jinja2),也就是說沒有默認(rèn)的模板引擎,從另一個角度上說,F(xiàn)astAPI 在模板引擎的選擇上變得更加靈活,極度舒適。
以 Jinja2 模板為例
安裝依賴
pip install jinja2pip install aiofiles # 用于 fastapi 的異步靜態(tài)文件
具體的用法
# -*- coding:utf-8 -*-from fastapi import FastAPI, requestfrom fastapi.staticfiles import StaticFilesfrom fastapi.templating import Jinja2Templatesimport uvicornapp = 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)時,必須帶上 request 的上下文對象,傳入?yún)?shù)放在同一字典。
這樣一來,又可以像 Flask 一樣的使用熟悉的 Jinja2 了,哈哈。
做個小總結(jié)的話就是 FastAPI 在用法上也是及其簡單,速度更快,性能更好,容錯率更高,整體上更牛逼。但是我在設(shè)想如此之快的框架,畢竟發(fā)布的時間不長,缺少像 Flask 框架的第三方庫和各種插件,所以要想真正意義上替代還是需要一定的時間,要冷靜,冷靜。
好啊,至此 FastAPI 的一些基本用法就差不多結(jié)束啦,F(xiàn)astAPI 的官方文檔有詳細(xì)的介紹和實(shí)例,入門篇到此結(jié)束。
官方文檔:https://fastapi.tiangolo.com/