PythonでWebアプリケーションのバックエンドを開発することになった際、技術選定で選択肢に上がる可能性が高いFastAPIについて紹介します。
フロントエンドにReact.jsやVue.jsを選択した場合、REST APIをバックエンドに立てる機会は多いです。FastAPIを使えば、学習コストを抑えめにしつつ、高速な開発が可能となります。
FastAPIとは
FastAPIは、Python 3.7以上でAPIを構築するための高性能なWebアプリケーションフレームワークです。開発者が迅速かつ効率的にREST APIアプリケーションを構築するのに役立ちます。
FastAPIはStarletteのWebサーバー上に構築され、自動データ検証、エラー処理、そして対話型APIドキュメントなど、Webアプリケーションの構築を容易にする機能を備えています。
FastAPIを選ぶ理由
エンジニアがFastAPIを選ぶべき理由は以下の通りです。
- スピード
FastAPIはNode.jsやGoと同等のパフォーマンスを持つ、高速なPythonウェブフレームワークの1つ
- 使いやすいドキュメント
詳細で使いやすい公式ドキュメントを提供している
- 型ヒント
型において、高度なデータ検証と変換を提供している
- オープンスタンダード
パス操作、リクエスト、パラメータ、セキュリティなどの宣言を含むOpenAPIなどに基づいている
- インタラクティブなAPIドキュメント
インタラクティブなAPIドキュメンテーションとWeb UI
- 並行性
備え付けの並行処理機能
- 依存性注入(DI)サポート
依存性注入をデフォルトでサポート
- バリデーション
備え付けの多彩な組み込みのバリデーション
これらの特徴は、Starletteフレームワーク上に構築されていることによる恩恵が多分に含まれています。データ検証部分はPydanticです。
こういった巨人の肩に乗ることで、async
/await
の予約語使用によって非同期コードをサポートしていたり、APIリクエストとレスポンスの高速で効率的な検証などが備わっています。
FlaskやDjangoのような他の主要なPythonフレームワークと比較すると実に高速です。
さらに、型ヒントを使用してAPIリクエストとレスポンスを自動的に検証し、JSONとの間でデータを自動的にシリアライズおよびデシリアライズするため、定型的なコードを排除します。
また、シンプルで直感的なAPIが付属しており、学習・使用が簡単です。
FastAPIのパフォーマンス
FastAPIはその高いパフォーマンスで知られています。
TechEmpowerというWebアプリケーションフレームワークのベンチマークを提供しているWebサイトを参考にしてみましょう。Uvicornの下で動作するFastAPIアプリケーションは、利用可能なPythonフレームワークの中で高速なものの1つであることがわかります。
ここでFastAPIの説明に不可欠なUvicornやStarletteについて説明しておきます。
- Uvicorn
ASGIサーバー(ベースのWebサーバーとして利用)
- Starlette
(Uvicornを使う)Webマイクロフレームワーク
- FastAPI
(Starletteを使う)APIマイクロフレームワーク
FastAPIは優れたパフォーマンスを提供する一方で、データ検証やシリアライゼーションなど、APIを構築する際に有益な多くの機能も提供していることが大きなメリットです。
したがって、FastAPIを使用することで開発時間やコード量が節約でき、より速いフレームワークで構築するよりも高い開発体験が得られます。
FastAPIと他のPythonフレームワークの比較
以下はFastAPIと代表的なPython製Webアプリケーションフレームワークの比較です。FastAPIの紹介記事なので、比較項目がややFastAPI寄りとなっていることをご留意ください。
フレームワーク | パフォーマンス | 柔軟さ | ドキュメント | 型ヒント | 開発コミュニティ |
---|
FastAPI | ◎(Python製高速フレームワークの一つ) | ◎(非同期サポートや依存性注入など) | 詳細で使いやすい | Pythonの型ヒントを仕様 | 急激に伸びている |
Django | △(フルスタックがゆえ) | △(モノシリック部分多し) | 包括的 | Pythonの型ヒント未使用 | 巨大かつ成熟している |
Flask | ◯(マイクロフレームワークなのでそこそこ速い) | ◎(柔軟で拡張性が高い) | 一般的 | Pythonの型ヒント未使用 | 巨大かつ成熟している |
Pyramid | ◯(マイクロフレームワークなのでそこそこ速い) | ◎(柔軟で拡張性が高い) | 一般的 | Pythonの型ヒント未使用 | DjangoやFlaskよりは小さい |
Tornado | ◯(非同期ネットワーク) | ◯(長時間接続やリアルタイム向け設計) | 一般的 | Pythonの型ヒント未使用 | Djangoやflaskよりは小さい |
FastAPI 用の開発環境のセットアップ
入門用に、FastAPIの開発を開始する手順を紹介していきます。
uvicorn
とfastapi
をインストールします。
pip
がすでにインストールされている前提で話を進めます。
ターミナルを開き、以下のコマンドを実行しましょう。
$ pip install uvicorn fastapi
最初の FastAPI アプリケーションの作成
簡単なFastAPIアプリケーションを作成していきましょう。
まずはmain.py
を作成します。
main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World"}
この時点で最初のアプリケーション自体は完成です。とても簡単ですね。
このアプリケーションは、ASGIサーバーであるUvicornを使って以下のコマンドを使って実行できます。
$ uvicorn main:app --reload
uvicorn main:app --reload
コマンドでは、main
はmain.py
ファイル(Pythonのモジュールに該当)を指し、app
はapp = FastAPI()
というオブジェクトです。--reload
フラグは、コード変更後にサーバーを再起動(ホットリロード)させます。
アプリが実行されると、
http://localhost:8000でブラウザを開き、JSONレスポンスを確認できます。また、
http://localhost:8000/docsで自動生成されたAPIドキュメントを、
http://localhost:8000/redocでReDocという別の自動生成APIドキュメントを参照できます。
FastAPIは、APIを定義するためのOpenAPIを使用して、すべてのAPIを含む「スキーマ(構造)」を生成します。このスキーマ定義には、APIパス、APIが受け取る可能性のあるパラメータなどが含まれます。
生のOpenAPIスキーマは
http://localhost:8000/openapi.jsonで確認できます。
FastAPIのルーティングとエンドポイント処理
FastAPIのルーティングとエンドポイント処理は、このフレームワークの重要な機能です。
ルーティング
FastAPIはデコレーターを使ってルートを定義します。
ルートとは、アプリケーションが公開するエンドポイント(エンドユーザーがアクセスできるURL定義)です。例えば、ルート("/"
)でHTTP GETリクエストを処理するルートを次のように定義できます。
@app.get("/")
async def root():
return {"message": "Hello World"}
@app.get("/")
デコレーターは、以下の関数がパス"/"
に対応し、GETリクエストを処理するために使用されるべきであることをFastAPIに伝えます。
エンドポイント処理
リクエストが来ると、FastAPIはルートとHTTPメソッド(GET、POSTなど) に従って処理します。デコレーターの下の関数(上の例で書いたroot()
など)が呼び出され、リクエストを処理し、レスポンスを生成します。
FastAPI の依存性注入システムの活用
FastAPIには、強力で直感的な依存性注入システム(DIとも言います)があります。その仕組みは以下の通りです。
- 依存性の宣言
FastAPIの依存関係はパス操作関数と同じパラメータを取ることができる関数です。たとえば、オプションのクエリパラメータを期待し、それらの値を含む辞書を返す依存関係を作成できます。
- 依存性の注入
FastAPIの依存性注入システムは、コードに必要な依存性を定義します。Depends
キーワードを使用して、パス操作関数で依存関係を宣言することで定義できます。
- ロジックの共有と関心の分離
依存性注入システムにより、コードの繰り返しを最小限に抑えられます。ロジックを共有し、セキュリティ、認証などを実施できます。また、追加の汎用オブジェクトをインスタンス化する代わりにビジネスロジックへ集中できるため、関心の分離にも役立ちます。
- テストが簡単
FastAPIは、テスト中の依存関係のオーバーライドを非常に簡単にします。これにより、コードの不必要なパッチを避けられます。
以下、Depends
を使った依存性注入定義の例です。common_parameters
に依存性を持たせることで、read_items()
にcommon_parameters
の特性を持たせます。
@app.get("/items/")
async def read_items(commons: Annotated[dict, Depends(common_parameters)]):
return commons
Pydantic と FastAPI によるデータの検証
Pydanticは強力なデータ検証機能を提供するPythonライブラリで、FastAPIをインストールすると自動的にインストールされます。
FastAPIにおいて、Pydanticは以下のような役割を持っています。
- Pydanticモデル
アプリケーションが受け取るデータを指定するためにPydanticモデルを定義します。これらのモデルはPythonの型アノテーションを使用して各フィールドの型を宣言します。
- 自動検証
リクエストを受信すると、FastAPIは自動的にPydanticモデルを使用してデータを検証します。データが無効な場合、明確かつ有益なエラーメッセージをクライアントに送り返します。
- フィールド制約
Pydanticではフィールドに制約を指定可能です。例えば、Field(..., min_length=5)
を使用することで、文字列フィールドが少なくとも5文字であることを保証できます。
- カスタムバリデーター
Pydanticではカスタムバリデーターを作成できます。これらはフィールドを検証するために呼び出される関数です。バリデーションに失敗した場合はValueError
例外で処理を止められます。
- フォームデータ
フォームデータも扱うことができます¹。フォームを表すPydanticモデルを作成し、FastAPIは自動的にこのモデルに対してフォームデータを検証します。
- 相互依存プロパティ
Pydanticにはroot_validator
デコレーターがあり、互いに依存するプロパティを検証できます。例えば、2つのパスワードフィールドが一致するかどうかをチェックするために使用できます。
FastAPIの自動バリデーションとエラー処理により、繰り返しバリデーションコードを書く必要がなくなります。
FastAPIの将来性
FastAPIは今でも積極的に開発が進められており、2023年7月にPydantic2へ対応する大型アップデートをしたばかりです。
年々、フロントエンドとバックエンドの開発分離が一般的になってから、より需要が高まっているため、今後もPythonにおけるREST APIフレームワークとしてスタンダードの座を守り続けるでしょう。
Python開発者にとって、手軽に外部APIを開発できるスキルは必須となるので、FastAPIを使いこなせると幅が広がります。Pydanticや認証周り、データベース操作を含めると難易度は上がりますが、ぜひ習得してみてください。