2026年11月14日、PythonのWebフレームワークFastAPIの0.163.0が公開されました。依存関係が同時に動く数を、Depends()のmax_concurrencyで絞れるようになったのが目玉です。
その前日、11月13日の0.162.6では、Python 3.10のサポートが終わりました。また、10月23日の0.162.0では、以前の記事で紹介したHTMLフォームの変更の一部が、元に戻されています。
FastAPIは、10月に入ってから版の更新がとても速いですよね。今回は、0.157から0.163までの主な変更を、実際に動かしながら見ていきます。
まずは前回からの流れを確認しよう¶
この連載では、10月にFastAPIの大きな変更を2回取り上げました。1回目は、HTMLフォームの扱いが変わった0.144から0.150まで、2回目は、JSONのnullと省略を区別するようになった0.151から0.156までです。
| 記事 | 取り上げた版 | 主な内容 |
|---|---|---|
| 1回目 | 0.144〜0.150 | チェックしなかったチェックボックスをFalseに、空欄を値なしに |
| 2回目 | 0.151〜0.156 | JSONのnullと省略の区別、知らないキーワード引数をエラーに |
| 今回 | 0.157〜0.163 | 依存関係の同時実行数、Python 3.10の終了、boolの扱いの見直し |
それぞれの記事は、こちらです。【関連記事】FastAPIが3日で0.150へ。HTMLフォームの扱いが変わった
【関連記事】FastAPIの変更は0.156まで続く
0.157から0.163で何が変わったのかを整理しよう¶
続いて、今回の範囲の主な変更を表にまとめます。内容は、FastAPIの公式リポジトリにあるリリースノートにもとづいています。
| 版 | 公開日 | 主な変更 |
|---|---|---|
| 0.157.0〜0.161.0 | 10月21日〜22日 | 複数のパラメーターモデルを組み合わせられるように |
| 0.160.0 | 10月22日 | パラメーターモデルのextraの設定を、同じ場所のほかの項目にも適用 |
| 0.162.0 | 10月23日 | 送られなかったboolのフォーム項目を、Falseとみなすのをやめた |
| 0.162.6 | 11月13日 | Python 3.10のサポートを終了 |
| 0.163.0 | 11月14日 | Depends()にmax_concurrencyを追加 |
0.160.0と0.162.0と0.162.6は、リリースノートで互換性を壊す変更として扱われています。PyPIの記録でも、0.163.0が必要とするPythonは3.11以上になっていました。
チェックボックスの扱いが見直された¶
まずは、前回の記事にも関係する大事な変更から見ていきましょう。1回目の記事では、0.147.0から、送られなかったboolのフォーム項目がFalseとして扱われるようになったことを紹介しました。
ところが、リリースノートによると、0.162.0でこの動きが元に戻されました。送られなかったboolの項目は、ほかの項目と同じように、宣言した既定値を使うか、足りない項目としてエラーになります。
3つの版で比べてみた¶
実際に、1回目の記事と同じように、既定値をTrueにしたnewsletterと、既定値をFalseにしたagreeを持つフォームで試しました。
from typing import Annotated
from fastapi import FastAPI, Form
app = FastAPI()
@app.post("/signup")
def signup(
name: Annotated[str, Form()],
newsletter: Annotated[bool, Form()] = True,
agree: Annotated[bool, Form()] = False,
):
return {"name": name, "newsletter": newsletter, "agree": agree}
nameだけを送ったときの結果を、0.143.5、0.150.0、0.163.0で比べました。手元のPython 3.11で、それぞれの版を新しい仮想環境に入れています。
| 版 | newsletter | agree |
|---|---|---|
| 0.143.5 | True | False |
| 0.150.0 | False | False |
| 0.163.0 | True | False |
0.150.0では、既定値をTrueにしていても、送られなかったnewsletterはFalseになっていました。0.163.0では、宣言した既定値のTrueに戻っています。
チェックボックスはどう書けばいいのか¶
リリースノートには、HTMLのチェックボックスには、既定値をFalseにしたboolを宣言するよう書かれています。上の例のagreeの書き方です。
チェックしなかったチェックボックスは、項目ごと送られてきません。既定値をFalseにしておけば、送られなかったときにFalseになり、ブラウザの動きと自然にかみ合います。
0.147から0.161までの版で、既定値をTrueにしたboolのフォーム項目を使っていた方は、0.162以降に上げると結果が変わる点に注意してください。
依存関係が同時に動く数を絞れるように¶
続いて、0.163.0の新機能です。FastAPIでは、Depends()を使って、データベースへの接続などの共通の処理を、依存関係として書けます。
リリースノートによると、Depends()にmax_concurrencyを指定すると、その依存関係が同時に動く数に上限を設けられるようになりました。インストールされた0.163.0の説明文によると、上限に達すると、次の呼び出しは前のものが終わるまで待ちます。
試してみた¶
外部のAPIを呼ぶ代わりに、0.2秒だけ待つ依存関係を用意し、同時に動いた数の最大値を数えました。6件のリクエストを、同時に送っています。
import asyncio
from typing import Annotated
from fastapi import Depends, FastAPI
running = 0
peak = 0
async def call_ai_api():
# 外部のAPIを呼ぶ代わりに、0.2秒待つだけの依存関係
global running, peak
running += 1
peak = max(peak, running)
await asyncio.sleep(0.2)
running -= 1
return "ok"
AIClient = Annotated[str, Depends(call_ai_api, max_concurrency=2)]
app = FastAPI()
@app.get("/answer")
async def answer(result: AIClient):
return {"result": result}
httpxを使ってアプリに直接リクエストを送り、結果を比べました。
| 条件 | 6件にかかった時間 | 同時に動いた最大数 |
|---|---|---|
| 0.163.0、上限なし | 0.2秒 | 6 |
| 0.163.0、max_concurrency=2 | 0.6秒 | 2 |
| 0.150.0、max_concurrency=2 | TypeErrorで動かない | - |
上限を2にすると、2件ずつ順番に動き、全体で3回分の0.6秒かかりました。同時に動く数が、きちんと2つまでに抑えられています。
どんなときに便利なのか¶
たとえば、外部のAIのAPIに、同時に送れるリクエストの数の制限がある場合です。上限を超えて送るとエラーになるなら、こちらで先に絞っておけば安心です。
説明文によると、上限は、同じDepends()のオブジェクトを使う呼び出しの間で共有されます。複数のルートで同じ上限を使いたいときは、上の例のように、Annotatedで1つにまとめておくとよいでしょう。
なお、説明文によると、上限はイベントループやワーカーのプロセスごとに数えられます。複数のプロセスで動かす場合は、プロセスの数だけ上限が増える点に気をつけましょう。
非同期処理の基本は、こちらで紹介しています。【関連記事】Pythonのasyncioとは?
Python 3.10のサポートが終わった¶
3つ目は、0.162.6でのPython 3.10のサポートの終了です。土台のStarletteは、10月13日の1.8.0で、すでに3.10のサポートを終えていました。
FastAPIも、これでようやく3.11以上が必要になりました。3.10で動かしている方は、Pythonの更新もあわせて計画しておきましょう。
3.10でpip installするとどうなるか¶
実際に、Python 3.10.22の仮想環境を新しく作り、pip install fastapiを実行してみました。入ったのは、3.10に対応している最後の系列の0.162.5でした。
pipは、今のPythonで使える中で最も新しい版を自動で選びます。そのため、3.10ではエラーにならず、0.163.0の新機能が使えない古い版が静かに入ることになります。
max_concurrencyを使おうとしてTypeErrorになったら、まずPythonの版を確かめてみてください。python --versionで、すぐに確かめられます。
主要なライブラリが3.10を外していく流れは、こちらでまとめました。【関連記事】Python 3.10のサポート終了から2週間、主要ライブラリの対応状況
そのほかの変更¶
0.157から0.161では、パラメーターモデルまわりの機能が続けて加わりました。パラメーターモデルとは、クエリやフォームの項目を、Pydanticのモデルにまとめて受け取る書き方です。
| 版 | 中身 |
|---|---|
| 0.157.0 | クエリ、ヘッダー、Cookieの複数のモデルを組み合わせられる |
| 0.158.0 | 複数のフォームのモデルを組み合わせられる |
| 0.159.0 | 省略できるクエリなどのモデルに対応 |
| 0.160.0 | extra="forbid"のモデルが、同じ場所のほかの項目も拒否するように |
| 0.162.5、0.162.7 | 処理が取り消されたときの、依存関係の後片付けを修正 |
0.160.0は、互換性を壊す変更です。extra="forbid"を設定したモデルを使っていると、ほかの引数で受け取っている項目まで拒否されるようになるので、上げたあとに確かめておきましょう。
上げる前にやっておきたいこと¶
最後に、FastAPIを0.163.0へ上げる前に確かめておきたいことを整理します。
| 順番 | 確認すること |
|---|---|
| 1 | Python 3.11以上を使っているか |
| 2 | 既定値をTrueにしたboolのフォーム項目の結果が、意図どおりか |
| 3 | extra="forbid"のパラメーターモデルが、ほかの項目を拒否していないか |
| 4 | 外部APIの同時接続数に制限があるなら、max_concurrencyを使えないか |
私は10年ほどエンジニアとして開発に関わってきましたが、外部のAPIの同時接続数の制限を超えてしまい、混み合う時間帯にだけエラーが出る問題に悩まされたことがあります。そのときは自分で仕組みを作って絞りましたが、Depends()の引数1つで済むのは、とても手軽です。
まとめ¶
2026年11月14日、FastAPI 0.163.0が公開されました。Depends()のmax_concurrencyで、依存関係が同時に動く数を絞れるようになり、0.162.6ではPython 3.10のサポートが終わっています。
0.162.0では、送られなかったboolのフォーム項目をFalseとみなす動きが元に戻されました。前回の記事の内容から変わった点なので、0.147から0.161を使っていた方は、上げたあとに一度確かめてみてください。
ここまでお読みいただきありがとうございました。