(入門篇)簡析一個比Flask和Tornado更高性能的API 框架FastAPI

用官方的話來說,FastAPI 是一種現代,快速(高性能)的 Web 框架,基於標準Python 類型提示使用 Python 3.6+ 構建 API


(入門篇)簡析一個比Flask和Tornado更高性能的API 框架FastAPI


FastAPI 站在巨人的肩膀上?

很大程度上來說,這個巨人就是指 Flask 框架。


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

技術背景:Py3.6+,Starlette,Pydantic

其實不僅僅是 FastAPI ,就連 Sanic 也是基於 Flask 快速開發的 Web API 框架。


廢話少說,代碼總是能給人帶來愉悅感 (抱頭),直接開懟。


安裝


<code>pip install fastapi 
pip install uvicorn/<code>


創建一個 main.py 文件


<code>from fastapi import FastAPI

app = FastAPI() # 創建 api 對象

@app.get("/") # 根路由
def root():
    return {"武漢": "加油!!!"}

@app.get("/say/{data}")
def say(data: str,q: int):
    return {"data": data, "item": q}/<code>


上面搭建了一個最簡單的 FastAPI 應用,看起來和 Flask 完全一樣,莫名的喜感。


使用以下命令來啟動服務器:


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


FastAPI 推薦使用 uvicorn 來運行服務,Uvicorn 是基於uvloop 和 httptools 構建的閃電般快速的 ASGI 服務器。


uvicorn main:app 指的是:

main:文件main.py

app: 創建的啟用對象

--reload: 熱啟動,方便代碼的開發


啟動界面如下:

(入門篇)簡析一個比Flask和Tornado更高性能的API 框架FastAPI


INFO 信息告訴我們已經監聽了本地的 8000 端口,訪問 http://127.0.0.1:8000 得到結果


(入門篇)簡析一個比Flask和Tornado更高性能的API 框架FastAPI

傳入參數


(入門篇)簡析一個比Flask和Tornado更高性能的API 框架FastAPI


再來看看 FastAPI 的異步代碼


<code>from fastapi import FastAPI

app = FastAPI() # 創建 api 對象

@app.get("/") # 根路由
async def root():
    return {"武漢": "加油!!!"}

@app.get("/say/{data}")
async def say(data: str,q: int = None):
    return {"data": data, "q": q}/<code>


開啟服務後訪問結果是一樣的。


在上面的路由方法中,我們傳入了一個 q 參數並且初始為 None,如果不給默認值,並且不傳參,代碼將直接報錯。

來看看 FastAPI 是如何處理錯誤的:

(入門篇)簡析一個比Flask和Tornado更高性能的API 框架FastAPI

可以看到,即使是報錯,也是優美的輸入一個帶有錯誤字段的 JSON,這就非常的友好了,這也是體現了 FastAPI 減少更多的人為錯誤的特性,返回也更加的簡潔直觀。


在命令行輸出:

(入門篇)簡析一個比Flask和Tornado更高性能的API 框架FastAPI


再來看看 FastAPI 的交互文檔

根據官方文檔,打開 http://127.0.0.1:8000/docs


看到:

(入門篇)簡析一個比Flask和Tornado更高性能的API 框架FastAPI


支持動態傳入數據:

(入門篇)簡析一個比Flask和Tornado更高性能的API 框架FastAPI

結果:

(入門篇)簡析一個比Flask和Tornado更高性能的API 框架FastAPI


從交互體驗上也是無比的友好,讓代碼在生產中更加健壯。


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


那麼再來看看最新的 Python web框架的性能響應排行版

(入門篇)簡析一個比Flask和Tornado更高性能的API 框架FastAPI


從併發性上來說是完全碾壓了 Flask (實際上也領先了同為異步框架的tornado 不少),看來 FastAPI 也真不是蓋的,名副其實的高性能 API 框架呀!


查詢參數


先來看看官方小 demo

<code>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]/<code>


該查詢是 ? URL中位於關鍵字之後的一組鍵值對,以&字符分隔。


在 url 中進行查詢

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


skip:查詢的起始參數

limit:查詢的結束參數


(入門篇)簡析一個比Flask和Tornado更高性能的API 框架FastAPI

成功返回查詢列表。


查詢參數類型轉換

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


來看看具體的例子:

<code>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/<code> 


看看其訪問路徑,執行以下的任何一種 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


可以發現任何大小寫的字母等都會被轉換成 bool 值的參數 True,這就是所謂模糊驗證參數,對於開發者來說這是個好消息。


要知道的是,如果 short 參數沒有默認值,則必須傳參,否則 FastAPI 將會返回類似以下的錯誤信息。


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


創建數據模型

前面說到 FastAPI 依賴 Pydantic 模塊,所以首先,你需要導入 Pydantic 的 BaseModel 類。


<code>from fastapi import FastAPI
from pydantic import BaseModel

# 請求主體類
class Item(BaseModel):
    name: str = "武漢加油 !!"
    description: str = None
    price: float = 233
    tax: float = None


app = FastAPI()


@app.post("/items/")
async def create_item(item: Item):
    return item/<code>


發送 post 請求來提交一個 Item(請求主體) 並返回,來看看提交過程。


(入門篇)簡析一個比Flask和Tornado更高性能的API 框架FastAPI


成功提交併返回 200 狀態碼

請求主體+路徑+查詢參數,在請求主體的基礎上加入 url 動態路徑參數 和 查詢參數

<code>from fastapi import FastAPI
from pydantic import BaseModel


class Item(BaseModel):
    name: str
    description: str = None
    price: float
    tax: float = None


app = 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/<code>


put 方法用於更新,傳入參數後成功返回一個字典。


關於模板引擎


FastAPI 不像 Flask 那樣自帶 模板引擎(Jinja2),也就是說沒有默認的模板引擎,從另一個角度上說,FastAPI 在模板引擎的選擇上變得更加靈活,極度舒適。


以 Jinja2 模板為例


安裝依賴

<code>pip install jinja2
pip install aiofiles # 用於 fastapi 的異步靜態文件/<code> 


具體的用法

<code># -*- 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") # 掛載靜態文件,指定目錄


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)/<code>


html 文件渲染

<code>

    武漢加油


    

高呼: {{ data }}

/<code>


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

(入門篇)簡析一個比Flask和Tornado更高性能的API 框架FastAPI


值得注意的是,在返回的 TemplateRespone 響應時,必須帶上 request 的上下文對象,傳入參數放在同一字典。


這樣一來,又可以像 Flask 一樣的使用熟悉的 Jinja2 了,哈哈。


做個小總結的話就是 FastAPI 在用法上也是及其簡單,速度更快,性能更好,容錯率更高,整體上更牛逼。但是我在設想如此之快的框架,畢竟發佈的時間不長,缺少像 Flask 框架的第三方庫和各種插件,所以要想真正意義上替代還是需要一定的時間,要冷靜,冷靜。


好啊,至此 FastAPI 的一些基本用法就差不多結束啦,FastAPI 的官方文檔有詳細的介紹和實例,入門篇到此結束。


官方文檔:https://fastapi.tiangolo.com/


分享到:


相關文章: