PythonのFastAPIチュートリアルをやってみた

Nov 14, 2021 09:25 · 1888 words · 4 minute read Python

Python製のWebフレームワーク「FastAPI」のチュートリアルをやってみました。

とても便利そうだったので、「いいな」と思った点をブログに書いておこうと思います。

目次

FastAPI?

Python製のWebフレームワークです。

Python製Webフレームワークの中では比較的新しく、Pythonの型ヒントと連携して受け取るパラメータの型を制限できたり、標準機能として非同期処理が組み込まれていたりします。

使い方はFlaskのようにシンプルなので、チュートリアルをみたらすぐに使い始めることができます。

パフォーマンスにも優れているらしく、Goに匹敵するパフォーマンスをだせるようです。

公式ドキュメント

チュートリアルはこちら

インストールと実行

まずはインストールして実行してみましょう。

インストール

$ pipenv install fastapi uvicorn 

サンプルコード

$ cat main.py
from fastapi import FastAPI

app = FastAPI()


@app.get("/")
async def root():
    return {"message": "Hello World"}

実行

$ uvicorn main:app --reload
INFO:     Will watch for changes in these directories: ['/Users/kapiecii/dev/python/fastapi-tutorial']
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     Started reloader process [19243] using statreload
INFO:     Started server process [19245]
INFO:     Waiting for application startup.
INFO:     Application startup complete.

127.0.0.1:8000にアクセスするとHello Worldが表示されます。

$ curl http://127.0.0.1:8000/ | jq .

{
  "message": "Hello World"
}

Swagger、ReDocとの連携

FastAPIでは、Pythonのコードから自動でドキュメントを生成してくれます。

対応している形式はSwagger形式とReDoc形式の2種類。

後述するEnumを使った指定をすることで、受け取ることができるパラメータの内容やレスポンスの内容も自動でドキュメントに反映してくれます。

パラメータ

GETパラメータやPOSTパラメータ、URLパスに含まれているパラメータを取得することができます。

また、Enumクラスを使って受け取るパラメータやレスポンスの内容を指定することもできます。

パラメータの検証機能も標準で用意されており、意図した形式ではないパラメータが送信された場合は、自動でjson形式のエラーメッセージを返してくれます。

自動で作成されるエラーメッセージの例

$ curl http://127.0.0.1:8000/models/a | jq .

{
  "detail": [
    {
      "loc": [
        "path",
        "model_name"
      ],
      "msg": "value is not a valid enumeration member; permitted: 'alexnet', 'resnet', 'lenet'",
      "type": "type_error.enum",
      "ctx": {
        "enum_values": [
          "alexnet",
          "resnet",
          "lenet"
        ]
      }
    }
  ]
}

async / await

async / awaitを使った非同期処理に標準で対応しています。

歴史のあるPythonのWebフレームワークでは標準で対応していないものもあり、そのような場合は別途非同期処理をするライブラリが必要でした。

FastAPIの場合には標準で対応しているので、async / awaitをつけるだけで非同期処理を実装することができます。

エラー処理

EnumやQueryといった方法で受け取るパラメータの値を制限をすることができます。

パラメータが開発者の意図した内容でなかった場合は、自動で下記のようなエラーメッセージを作成してくれます。

サンプルコード

$ cat main.py
from enum import Enum
from typing import Optional
from fastapi import FastAPI, Query


class ModelName(str, Enum):
    alexnet = "alexnet"
    resnet = "resnet"
    lenet = "lenet"


app = FastAPI()


@app.get("/")
async def root():
    return {"message": "Hello World"}


@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
    if model_name == ModelName.alexnet:
        return {"model_name": model_name, "message": "Deep Learning FTW!"}

    if model_name.value == "lenet":
        return {"model_name": model_name, "message": "LeCNN all the images"}

    return {"model_name": model_name, "message": "Have some residuals"}


@app.get("/items/")
async def read_items(q: Optional[str] = Query(None, min_length=3, max_length=50)):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results

値が正常な場合

$ curl http://127.0.0.1:8000/models/alexnet | jq .

{
  "model_name": "alexnet",
  "message": "Deep Learning FTW!"
}

開発者が意図した値でない場合

$ curl http://127.0.0.1:8000/models/a | jq .

{
  "detail": [
    {
      "loc": [
        "path",
        "model_name"
      ],
      "msg": "value is not a valid enumeration member; permitted: 'alexnet', 'resnet', 'lenet'",
      "type": "type_error.enum",
      "ctx": {
        "enum_values": [
          "alexnet",
          "resnet",
          "lenet"
        ]
      }
    }
  ]
}

値が正常な場合

$ curl http://127.0.0.1:8000/items/?q=aaa | jq .

{
  "items": [
    {
      "item_id": "Foo"
    },
    {
      "item_id": "Bar"
    }
  ],
  "q": "aaa"
}
$ curl http://127.0.0.1:8000/items/?q=a | jq .

{
  "detail": [
    {
      "loc": [
        "query",
        "q"
      ],
      "msg": "ensure this value has at least 3 characters",
      "type": "value_error.any_str.min_length",
      "ctx": {
        "limit_value": 3
      }
    }
  ]
}

セキュリティと認証認可

OAuthやJWTなどにも対応しています。

サンプルコードを含めた公式ドキュメントも充実していました。

JWTについては、こちらも参考になると思います。

テスト

TestClientが用意されており、テストも快適に行えそうです。

最後に

FastAPIは「Flaskのようなシンプルさと現代的な機能を併せ持ったWebフレームワーク」という印象でした。

さっと開発するには非常に良さそうですが、大規模なシステムを作る場合にはフルスタックなフレームワークを使いたくなるのかもしれません。

tweet Share