Files
fastapi/docs/ja/docs/tutorial/dependencies/dependencies-with-yield.md
Sebastián Ramírez b0e99d66e8 🌐 Update translations for ja (update-outdated) (#14588)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Yurii Motov <yurii.motov.monte@gmail.com>
Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
Co-authored-by: Maruo.S <raspi-maru2004@outlook.jp>
2026-02-04 17:44:21 +01:00

16 KiB
Raw Blame History

yieldを持つ依存関係

FastAPIは、いくつかの終了後の追加のステップを行う依存関係をサポートしています。

これを行うには、returnの代わりにyieldを使い、その後に追加のステップ(コード)を書きます。

/// tip | 豆知識

yieldは必ず依存関係ごとに1回だけ使用するようにしてください。

///

/// note | 技術詳細

以下と一緒に使用できる関数なら何でも有効です:

これらは FastAPI の依存関係として使用するのに有効です。

実際、FastAPIは内部的にこれらつのデコレータを使用しています。

///

yieldを持つデータベースの依存関係

例えば、これを使ってデータベースセッションを作成し、終了後にそれを閉じることができます。

レスポンスを作成する前に、yield文より前のコード(およびyield文を含む)が実行されます:

{* ../../docs_src/dependencies/tutorial007_py39.py hl[2:4] *}

生成された値は、path operationsや他の依存関係に注入されるものです:

{* ../../docs_src/dependencies/tutorial007_py39.py hl[4] *}

yield文に続くコードは、レスポンスの後に実行されます:

{* ../../docs_src/dependencies/tutorial007_py39.py hl[5:6] *}

/// tip | 豆知識

asyncや通常の関数を使用することができます。

FastAPI は、通常の依存関係と同じように、それぞれで正しいことを行います。

///

yieldtryを持つ依存関係

yieldを持つ依存関係でtryブロックを使用した場合、その依存関係を使用した際にスローされたあらゆる例外を受け取ることになります。

例えば、途中のどこかの時点で、別の依存関係やpath operationの中で、データベーストランザクションを「ロールバック」したり、その他の例外を作成したりするコードがあった場合、依存関係の中で例外を受け取ることになります。

そのため、依存関係の中にある特定の例外をexcept SomeExceptionで探すことができます。

同様に、finallyを用いて例外があったかどうかにかかわらず、終了ステップを確実に実行することができます。

{* ../../docs_src/dependencies/tutorial007_py39.py hl[3,5] *}

yieldを持つサブ依存関係

任意の大きさや形のサブ依存関係やサブ依存関係の「ツリー」を持つことができ、その中でyieldを使用することができます。

FastAPI は、yieldを持つ各依存関係の「終了コード」が正しい順番で実行されていることを確認します。

例えば、dependency_cdependency_bに、そしてdependency_bdependency_aに依存することができます:

{* ../../docs_src/dependencies/tutorial008_an_py39.py hl[6,14,22] *}

そして、それらはすべてyieldを使用することができます。

この場合、dependency_cは終了コードを実行するために、dependency_b(ここではdep_bという名前)の値がまだ利用可能である必要があります。

そして、dependency_bdependency_a(ここではdep_aという名前)の値を終了コードで利用できるようにする必要があります。

{* ../../docs_src/dependencies/tutorial008_an_py39.py hl[18:19,26:27] *}

同様に、yieldを持つ依存関係とreturnを持つ他の依存関係をいくつか持ち、それらの一部が他の一部に依存するようにもできます。

また、単一の依存関係を持っていて、yieldを持つ他の依存関係をいくつか必要とすることもできます。

依存関係の組み合わせは自由です。

FastAPI は、全てが正しい順序で実行されていることを確認します。

/// note | 技術詳細

これはPythonのContext Managersのおかげで動作します。

FastAPI はこれを実現するために内部的に使用しています。

///

yieldHTTPExceptionを持つ依存関係

yieldを持つ依存関係を使い、何らかのコードを実行し、その後にfinallyの後で終了コードを実行しようとするtryブロックを持てることが分かりました。

また、exceptを使って発生した例外をキャッチし、それに対して何かをすることもできます。

例えば、HTTPExceptionのように別の例外を発生させることができます。

/// tip | 豆知識

これはやや高度なテクニックで、ほとんどの場合は本当に必要にはなりません。例えば、path operation 関数など、アプリケーションコードの他の場所から(HTTPExceptionを含む)例外を発生させられるためです。

ただし必要であれば使えます。 🤓

///

{* ../../docs_src/dependencies/tutorial008b_an_py39.py hl[18:22,31] *}

例外をキャッチして、それに基づいてカスタムレスポンスを作成したい場合は、カスタム例外ハンドラ{.internal-link target=_blank}を作成してください。

yieldexceptを持つ依存関係

yieldを持つ依存関係でexceptを使って例外をキャッチし、それを再度raiseしないまたは新しい例外をraiseしない場合、通常のPythonと同じように、FastAPIは例外があったことに気づけません:

{* ../../docs_src/dependencies/tutorial008c_an_py39.py hl[15:16] *}

この場合、(HTTPExceptionやそれに類するものをraiseしていないためクライアントには適切にHTTP 500 Internal Server Errorレスポンスが返りますが、サーバーにはログが一切残らず、何がエラーだったのかを示す他の手がかりもありません。 😱

yieldexceptを持つ依存関係では常にraiseする

yieldを持つ依存関係で例外をキャッチした場合、別のHTTPExceptionなどをraiseするのでない限り、元の例外を再raiseすべきです

raiseを使うと同じ例外を再raiseできます:

{* ../../docs_src/dependencies/tutorial008d_an_py39.py hl[17] *}

これでクライアントは同じHTTP 500 Internal Server Errorレスポンスを受け取りますが、サーバーのログにはカスタムのInternalErrorが残ります。 😎

yieldを持つ依存関係の実行

実行の順序は多かれ少なかれ以下の図のようになります。時間は上から下へと流れていきます。そして、各列はコードを相互作用させたり、実行したりしている部分の一つです。

sequenceDiagram

participant client as Client
participant handler as Exception handler
participant dep as Dep with yield
participant operation as Path Operation
participant tasks as Background tasks

    Note over client,operation: Can raise exceptions, including HTTPException
    client ->> dep: Start request
    Note over dep: Run code up to yield
    opt raise Exception
        dep -->> handler: Raise Exception
        handler -->> client: HTTP error response
    end
    dep ->> operation: Run dependency, e.g. DB session
    opt raise
        operation -->> dep: Raise Exception (e.g. HTTPException)
        opt handle
            dep -->> dep: Can catch exception, raise a new HTTPException, raise other exception
        end
        handler -->> client: HTTP error response
    end

    operation ->> client: Return response to client
    Note over client,operation: Response is already sent, can't change it anymore
    opt Tasks
        operation -->> tasks: Send background tasks
    end
    opt Raise other exception
        tasks -->> tasks: Handle exceptions in the background task code
    end

/// info | 情報

1つのレスポンス だけがクライアントに送信されます。それはエラーレスポンスの一つかもしれませんし、path operationからのレスポンスかもしれません。

いずれかのレスポンスが送信された後、他のレスポンスを送信することはできません。

///

/// tip | 豆知識

path operation 関数のコードで例外をraiseした場合、HTTPExceptionを含め、それはyieldを持つ依存関係に渡されます。ほとんどの場合、その例外が正しく処理されるように、yieldを持つ依存関係から同じ例外、または新しい例外を再raiseしたくなるでしょう。

///

早期終了とscope

通常、yieldを持つ依存関係の終了コードは、クライアントにレスポンスが送信された後に実行されます。

しかし、path operation 関数からreturnした後に依存関係を使う必要がないと分かっている場合は、Depends(scope="function")を使って、レスポンスが送信される前に、path operation 関数のreturn後に依存関係を閉じるべきだとFastAPIに伝えられます。

{* ../../docs_src/dependencies/tutorial008e_an_py39.py hl[12,16] *}

Depends()は、以下のいずれかを取るscopeパラメータを受け取ります:

  • "function": リクエストを処理するpath operation 関数の前に依存関係を開始し、path operation 関数の終了後に依存関係を終了しますが、クライアントにレスポンスが返されるに終了します。つまり、依存関係関数はpath operation 関数周囲で実行されます。
  • "request": リクエストを処理するpath operation 関数の前に依存関係を開始し("function"を使用する場合と同様)、クライアントにレスポンスが返されたに終了します。つまり、依存関係関数はリクエストとレスポンスのサイクルの周囲で実行されます。

指定されておらず、依存関係にyieldがある場合、デフォルトでscope"request"になります。

サブ依存関係のscope

scope="request"(デフォルト)を持つ依存関係を宣言する場合、どのサブ依存関係も"request"scopeを持つ必要があります。

しかし、"function"scopeを持つ依存関係は、"function""request"scopeを持つ依存関係を持てます。

これは、いずれの依存関係も、サブ依存関係より前に終了コードを実行できる必要があるためです(終了コードの実行中にサブ依存関係をまだ使う必要がある可能性があるためです)。

sequenceDiagram

participant client as Client
participant dep_req as Dep scope="request"
participant dep_func as Dep scope="function"
participant operation as Path Operation

    client ->> dep_req: Start request
    Note over dep_req: Run code up to yield
    dep_req ->> dep_func: Pass dependency
    Note over dep_func: Run code up to yield
    dep_func ->> operation: Run path operation with dependency
    operation ->> dep_func: Return from path operation
    Note over dep_func: Run code after yield
    Note over dep_func: ✅ Dependency closed
    dep_func ->> client: Send response to client
    Note over client: Response sent
    Note over dep_req: Run code after yield
    Note over dep_req: ✅ Dependency closed

yieldHTTPExceptionexcept、バックグラウンドタスクを持つ依存関係

yieldを持つ依存関係は、さまざまなユースケースをカバーし、いくつかの問題を修正するために、時間とともに進化してきました。

FastAPIの異なるバージョンで何が変わったのかを知りたい場合は、上級ガイドの上級の依存関係 - yieldHTTPExceptionexcept、バックグラウンドタスクを持つ依存関係{.internal-link target=_blank}で詳しく読めます。

コンテキストマネージャ

「コンテキストマネージャ」とは

「コンテキストマネージャ」とは、with文の中で使用できるPythonオブジェクトのことです。

例えば、ファイルを読み込むにはwithを使用することができます:

with open("./somefile.txt") as f:
    contents = f.read()
    print(contents)

その後のopen("./somefile.txt")は「コンテキストマネージャ」と呼ばれるオブジェクトを作成します。

withブロックが終了すると、例外があったとしてもファイルを確かに閉じます。

yieldを持つ依存関係を作成すると、FastAPI は内部的にそれをコンテキストマネージャに変換し、他の関連ツールと組み合わせます。

yieldを持つ依存関係でのコンテキストマネージャの使用

/// warning | 注意

これは多かれ少なかれ、「高度な」発想です。

FastAPI を使い始めたばかりの方は、とりあえずスキップした方がよいかもしれません。

///

Pythonでは、以下の2つのメソッドを持つクラスを作成する: __enter__()__exit__()ことでコンテキストマネージャを作成することができます。

また、依存関数の中でwithasync with文を使用することによってyieldを持つ FastAPI の依存関係の中でそれらを使用することができます:

{* ../../docs_src/dependencies/tutorial010_py39.py hl[1:9,13] *}

/// tip | 豆知識

コンテキストマネージャを作成するもう一つの方法はwithです:

これらを使って、関数を単一のyieldでデコレートすることができます。

これは FastAPI が内部的にyieldを持つ依存関係のために使用しているものです。

しかし、FastAPIの依存関係にデコレータを使う必要はありませんそして使うべきではありません

FastAPIが内部的にやってくれます。

///