🐍
FastAPIでDIのメソッドにパラメータを渡す(同期も非同期も)
始めに
FastAPIにてメソッドやクラスをDIできますが、DI時に部分的に処理を差し替えたい時があります。その時にパラメータを渡せば処理を差し替えられますが、少々ハマったのでそれをブログにします。
環境
- Python
- 3.12.4
- FastAPI
- 0.112.0
実装
同期処理の場合
Dependsで呼び出す際にlambda
でパラメータを使用すれば呼び出せます。ただし、非同期処理は呼び出せないので注意してください。コンパイルエラーは発生しませんが何も起こりません。
async def async_printer(msg: str) -> None:
print(msg)
def printer(msg: str) -> None:
print(msg)
@router.post("/run", response_model=bool)
async def di_test(
*,
_: None = Depends(lambda: printer(msg="SYNC")),
__: None = Depends(lambda: async_printer(msg="ASYNC")),
) -> Any:
# 呼び出すと printer だけしか呼ばれていないことがわかる
# SYNC
非同期処理の場合
class
にしたうえで、async def __call__
に定義することで処理が呼ばれます。Annotated
を使用してももちろん呼ばれます。
class DIClass:
def __init__(self, msg: str):
self.msg = msg
async def __call__(
self,
):
print(self.msg)
AsyncDi = Annotated[None, Depends(DIClass(msg="ASYNC THREE"))]
@router.post("/run", response_model=bool)
async def di_test(
*,
___: None = Depends(DIClass(msg="ASYNC TWO")),
____: AsyncDi,
) -> Any:
# 呼び出すと、次の順でログが出力される
# ASYNC TWO
# ASYNC THREE
ユースケース
- バリデーション処理を部分的に差し替える
- CSV処理で使用しようとしていました
処理が複雑になるので、微妙といえば微妙かもしれません。ただ、次のメリットがあるので一考の余地があるかもしれません。
- 本処理をWriterインスタンスを使用しつつ、ValidationをReaderインスタンスにする
- 本処理側はすでにバリデーションがかかったファイルを扱うことで、本処理を整理できる
class CsvFileValidator:
"""
処理に必要なものをDIで取得する共通部品
"""
def __init__(self, validator: Callable):
self.validator = validator
async def __call__(
self,
session: SessionReaderDep, # Validate処理でReaderインスタンスを取得する
file: UploadFile=File(...),
current_user=Security(get_current_user),
):
return await self.validator(session, file, current_user)
async def csv_validation(session: AsyncSession, file: UploadFile, current_user: User) -> None:
"""
具体的なチェック処理
"""
pass
FileValidated = Annotated[None, Depends(CsvFileValidator(csv_validation))]
@router.post("/run", response_model=bool)
async def di_test(
*,
sesison: SessionWriterDep, # 本処理ではWriterインスタンスを使用する
_: FileValidated # DI時にバリデーションをしてくれる
) -> Any:
return True
ソースコード
終わりに
ChatGPT
に確認しても、非同期処理でDI時にパラメータを与える方法を教えてくれなくて困りました。最初から公式のヘルプには書いてあったので、隅々まで読んでみることが必要ですね。
参考情報
- SpringのBean定義(Java Config)で型が重複する場合のインジェクション方法
- FastAPI公式ヘルプのパラメータ化された依存関係
Discussion