全面擁抱 FastApi — 多應用程序項目結構規劃
- 2020 年 4 月 1 日
- 筆記
FastAPI最近比較火,自從看到這款框架後就一直在關注着。據官方文檔上的介紹它是一個並發性可以和 NodeJS 以及 Go 相媲美的 web 框架,具有強大的性能
本人最近也是一直在使用和學習 FastApi,相比之前用的框架性能確實有很大的提升,用完後有如下幾點感受:
- 性能並發更強了,支持異步 async
- 基於 Pydantic 的類型聲明,自動校驗參數
- 自動生成交互式的 API 接口文檔
- 上手簡單,能快速編碼
上手快是真的,上班期間零零散散的看了兩天文檔,就將現有的一個服務改成 FastApi 服務了,配合 gunicorn+uvicorn 部署,最近測試也沒出現什麼問題。
由於之前 Flask 用的比較多,在 FastAPI 上隱隱約約能看到 Flask 的影子,兩者的設計範式很類似。
例如:更大的應用程序服務多文件多 url 處理功能,在 Flask 中稱之為藍圖的,對應 FastApI 中的 APIRouter
使用 APIRouter
上面說過和 Flask 非常的類似,比如創建一個簡單的 FastAPI 服務
from fastapi import FastAPI app = FastAPI() @app.get("/") async def index(): return "Hello world" @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
上述代碼中有兩個視圖函數以及 url 路徑,現在這種情況看起來還好
但是如果服務中視圖函數有 10 個或者更多呢?這時候就不建議寫在一個文件裏面了,因為代碼不易維護且顯得臃腫
這時候便要考慮將視圖函數分文件處理了,APIRouter 就給我們提供了在多個文件中註冊路由的功能。
類似生活中的常用的插線板,能提供更多的插口插入電器插頭,然後我們最終只需要將這一個或多個插線板 (APIRouter) 插到主線路 (app = FastAPI() ) 即可
比如服務中兩個應用模塊,combination 和 level 分別對應兩個應用模塊,通過 APIRouter 來對其路由進行註冊,用法如下:
combination.py 」
from fastapi import APIRouter router = APIRouter() @router.get("/users/", tags=["users"]) async def read_users(): return [{"username": "Foo"}, {"username": "Bar"}] @router.get("/users/me", tags=["users"]) async def read_user_me(): return {"username": "fakecurrentuser"}
相應的 level.py 也能這樣寫,但是你是否會發現創建了兩個 APIRouter() 的對象
這樣當然也是可以的,官方文檔就是這樣舉例的,你甚至可以創建更多。不過我覺得兩個應用創建兩個 router 感覺有點 "浪費", 我們是否可以這樣:只創建一個 router ,然後在每個模塊導入創建好的 router,當然也是可以,效果一樣
這部分就是另起文件,創建 router, 代碼非常簡單,但是記住要導入模塊對應視圖函數,
routers.py 」
from fastapi import APIRouter router = APIRouter() from ..combination import views from ..level2 import views
接下來就是在模塊視圖函數中導入上述創建好的 router
from app.routers import router @router.get("/users/", tags=["users"]) async def read_users(): return [{"username": "Foo"}, {"username": "Bar"}] @router.get("/users/me", tags=["users"]) async def read_user_me(): return {"username": "fakecurrentuser"}
另外一個模塊也是一樣的導入,代碼就不貼了,理解就行
註冊 APIRouter
最後一個步驟就是要將我們的 APIRouter 註冊到核心對象上去,就像前面舉的示例將插線板插到主線路插口上
和之前我們創建主文件一樣導入 FastApi
from fastapi import FastAPI app = FastAPI() app.include_router(routers.router, prefix="/api")
其中 include_router() 函數就是上面說的註冊。
這時候就完成了,使用該 app 來啟動服務即可。當然你也可以將該核心對象包裝成函數返回,然後在主目錄調用啟動,
def create_app(): app = FastAPI() app.include_router(routers.router, prefix="/nlp_service") return app
主目錄中創建 main.py 文件調用啟動,
from app import create_app app = create_app()
啟動命令:
uvicorn main:app --host=0.0.0.0 --port=8800

本節完!敬請期待後續更多更新