前言
終於有了第一個使用 FastApi 編寫的線上服務, 在開發的過程中還是遇到了些問題, 這里記錄一下
正文
目錄結構
我們知道, FastApi 的啟動方式推薦使用 uvicorn, 其啟動方式大致為 uvicorn main:app
, 實際上 main 為該文件的名字, app 為生成的 FastApi 對象, 那么, 對於一個比較大的項目, 我們應該怎樣去布局項目呢? 我們參考了 https://github.com/nsidnev/fastapi-realworld-example-app 他是在名為 app 的文件夾中的 main.py 文件存放最大的 app, 在 該文件夾下存放各種邏輯文件, 例如: 基礎的數據庫相關放在 db 文件夾中, 公共的邏輯放在 core 文件夾中, 接口相關放在 api 文件夾中等等...
因為 app 已經放置在app文件夾中的 main.py 文件中, 啟動時則是在根目錄輸入 uvicorn app.main:app
main.py
多級路由處理
類似於 Flask 的藍圖, FastApi 有更為簡單的寫法
這里以我們的項目為例, 我們有多層, 最頂級的 app 在 app 文件夾的 main.py 中, files 相關的 api 在 app > api > routers > files > api.py
中
我們從最里層的 api.py 看起, 最里層的 app > api > routers > files > api.py
大致是這樣的
在 FastApi 中, 多層路由的每一層都可以設置生成一個 APIRouter 對象
我們再看上一層, 也就是 app > api > routers > api.py
這個 api.py 作為 routers 的整個的 router, 同樣生成了 APIRouter 對象, 但是該對象因為並不是最下層的路由, 所以導入下層路由的 router 通過 router.include_router
注冊到這個上層路由中, prefix 是路由前綴
我們再看 app > main.py
在最外層, 我們就生成了需要使用 uvicorn
啟動的 app 對象, app 對象可以直接使用 include_router 注冊路由, 那么其實結構是 最底層的 router 直接面向邏輯, 而外層的一層都通過 include_router 注冊他, 同時在注冊時可以設置前綴等操作
啟動與結束事件
有時候, 我們希望在服務啟動時進行一些操作, 比如初始化數據庫連接池等操作, 原來我們可能是直接寫在生成 app 的時候, 而在服務關閉時關閉連接池則需要費些心思, FastApi提供了事件, 我們注冊到某個事件后其在指定的時候執行我們注冊的功能, 還拿 main.py 舉例
add_event_handler 代表添加事件, 參數1為事件的名字, 默認的有一些, 比如 startup, 參數二則是傳入我們自寫的函數邏輯, 注意接收一個參數為 app 對象
webSocket狀態捕捉
FastApi 同樣支持 webSocket, 其官方給的例子類似
其實這種如果客戶端主動斷開的話, 因服務端是 while 1
, 還在嘗試從一個已經關閉的wb里獲取數據, 所以會報錯, 體現在接口里就是500, 所以我們需要捕捉此異常
依賴注入
我們知道, 在 Flask 中有一個 g 對象, 他穿插在 Flask 的生命周期中, 我們可以給某些接口使用裝飾器來做一些通用的操作, 然后將數據依附在 g 中傳遞給具體的邏輯中方便使用, 那么在 FastApi 中也可以做到, 例如
我們在接收參數時, 可以指定某個參數是由 Depends
傳出, 這便意味着這個參數不是由請求傳遞的, 而是由我們指定的邏輯生成后傳入的, 比如上面的代碼, 我們接受參數 fs, 這個參數 fs 是 Depends
生成的, 那么此參數就是這個接口的 依賴, 請求進入時會執行 Depends
包裹的函數, 也就是 get_bucket
函數, 此函數是我們自己寫的, 目的是將數據庫連接生成, 然后作為參數 fs 傳入具體邏輯, 在里面使用
后台任務
比如我們有一個接口, 這個接口需要向某個郵箱發送郵件, 因為發送郵件這個動作可能持續幾秒, 我們不能讓這個請求在這邊夯住直到發送完成, 我們希望理想的效果是: 接口立即返回任務提交成功,由后台發送郵件, FastApi 的 background tasks
可以幫我們做到
如上圖, 我們在接收參數時加上一個 BackgroundTasks
類型的參數, 這個參數並不是由請求傳遞, 當我們希望將某個邏輯放到背后去執行時, 只需要 .add_task
即可, 他接受多個參數, 參數1為要執行的函數名, 后面是該函數的參數, 既可以使用順序傳參也可使用關鍵字傳參
當我們注冊后, FastApi 只是將其加入了 BackgroundTasks
中, 並不會立即執行, 而是在這個請求響應后才執行, 也就是在 return 后