メインコンテンツへスキップ

FastAPI×Streamlitでアプリ開発(Getリクエスト)

·☕6分
#テック系 #Python #FastAPI #Pydantic #Streamlit
Rakuichi
著者
Rakuichi
ヴィッセルサポのIT屋
目次

PythonでAPIを作成するときに使われるFastAPIですが、やはりアプリにしたいというところで、フロントエンドの部分を作るのに困っていました。手っ取り早く画面を作るには、そこまでフロントエンドの技術を持っていないので…。そんな時、StreamlitというPythonで簡単にアプリが作れるフレームワークがあることを知りました。

Streamlitは、リッチなアプリが作れる便利なフレームワークです。このフレームワークは、データを扱うアプリの作成をターゲットとしています。そのため、データ分析や機械学習系のツールを作る際に、手っ取り早くアプリ化するには、とても適していると思います。

ただ今回は、こちらのStreamlitをあくまでフロントエンド用に利用し、FastAPIで作成したAPIサーバとやり取りさせることで、Pythonだけでバックエンドとフロントエンドを分離したアプリを作成していきます。

実際に作成してしているアプリの紹介
#

こちらの内容に関しては記事執筆時点(2022年10月7日)のものなので、リポジトリの内容とずれがあるかもしれません。

↓リポジトリ

練習で作成しているアプリの画面です。

単純なGetリクエスト
画像データのやり取り

本記事では足し算機能についてのみ紹介いたします。 今後も様々な機能を、練習として実装していこうと思っています(機能毎の記事も書くかもしれません)。

作成中のアプリでは以下のようなプロジェクト構成をしています。マイクロサービスというならPipfileも分けるべきなのですが、開発の簡略化のためにまとめています。

poms
├─.vscode             VSCode開発用設定
│      settings.json
├─backend             バックエンド(FastAPI)ソース
│  │  main.py         アプリ立ち上げ用
│  │  __init__.py
│  ├─config           バックエンドの設定関連
│  ├─libs             バックエンドのロジック部分
│  ├─schemas          Pydanticモデル定義
│  └─v1               API作成部分
│      │  api.py
│      │  __init__.py
│      └─routers      エンドポイント定義
├─docs                全般のドキュメント
└─frontend            フロントエンド(Streamlit)ソース
│   │  home.py        立ち上げ用(ホーム画面)
│   │  __init__.py 
│   ├─config          フロントの設定関連
│   └─pages           フロントの各ページ
├─Pipfile
├─Pipfile.lock
└─README.md

なお、以下の説明では、上記のプロジェクト構成は利用せずにシンプルな形で説明しています。

足し算機能を作成してみる
#

非常に単純な足し算機能を作成してみます。役割分担としては以下のようになります。

  • Streamlit(フロントエンド)
    • aとb、2つのクエリパラメータ(数値)の入力
    • バックエンドへの足し算処理リクエスト
    • レスポンスを受け取って表示
  • FastAPI(バックエンド)
    • 足し算エンドポイントの作成

記事内ではソースを簡略化していますので、実際の実装を見たい方はリポジトリをご参照ください。

繰り返しになりますが、以下のコードは上記のプロジェクト構成に依存していません。記事内ではコードを簡略化していますので、実際の実装を見たい方はリポジトリをご参照ください。

フロントエンド部分
#

APIへのリクエストはrequestsライブラリを利用します。ボタンを用意して、そのボタンがクリックされたらif submitted内の処理が走り、リクエストが実行されます。

import requests
import streamlit as st

with st.form("get_sample_form"):
    # リクエスト先
    endpoint_url = "http://127.0.0.1:8000/plus"
    # 表示と入力
    st.write("## 足し算(a + b)")
    st.write("Getリクエスト(クエリ付き)")
    a = st.number_input("a を入れてください")
    b = st.number_input("b を入れてください")

    # 計算実行ボタン
    submitted = st.form_submit_button("計算する")
    if submitted:
        # ボタン押下時の処理
        response = requests.get(endpoint_url, params={"a": a, "b": b})
        if response.status_code == 200:
            result = response.json()["result"]
            st.success(f"**{result}**")
        else:
            st.error(f"{response.status_code}エラーが発生しました。詳細は以下を参照ください")
            st.json(response.json())

Streamlitは公式ドキュメントが充実しているので、ボタンや入力欄の作成はそちらを見てください。処理の流れとしては、受け取った入力をrequestsでGetリクエストするだけです。st.number_input()を利用しているので、数値以外は入力できません。また、デフォルトで0がはいっているため、中身がないままリクエストされることもありません。

バックエンド部分
#

今回、Python3.10を利用しているので、型ヒントの書き方がPython3.9までとは違う点に注意が必要です。Python3.9までの方はint | floatとなっている部分を、Union[int, float]としてください(from typing import Union)。

from fastapi import FastAPI, Query
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel, Field


class AddIn(BaseModel):
    """GET /plus の入力"""

    a: int | float = Field(Query(description="足される数"))
    b: int | float = Field(Query(description="足される数"))


class AddOut(BaseModel):
    """GET /plus の出力"""

    result: int | float = Field(description="足し算の結果")


app = FastAPI()

# CORS設定(公式ドキュメント:https://fastapi.tiangolo.com/ja/tutorial/cors/)
app.add_middleware(
    CORSMiddleware,
    allow_origins=["http://localhost", "http://localhost:8501"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

@app.get("/plus", response_model=samples.AddOut)
async def add(query: samples.AddIn = Depends()):
    """足し算

    Parameters
    ----------
    a : int | float
        足される数\\
    b : int | float
        足す数
    """
    return {"result": query.a + query.b}

CORSの設定をしておかないと、8501ポートで開いているStreamlitからのリクエストを遮断する可能性があります。この辺りは公式ドキュメントをご覧ください

公式ドキュメント:CORS (オリジン間リソース共有) - FastAPI

実行画面
#

フロントエンドとバックエンドをそれぞれ立ちあげて、アプリ画面からリクエストを実行してみます。

-20+40=20

計算結果を表示できました。

まとめ
#

StreamlitとFastAPIを使うことで、Pythonのみでも簡単にフロントエンドとバックエンドを分離したアプリを作成することができました。フロントにややこしい処理を実装する必要がないため、プログラムの管理もしやすかったです。また、React等を学んで、フロントのみ切り替えることも簡単なので、まずアプリを作るという点では非常に使いやすいですね。

今後は、上で紹介したモザイク機能に関する記事や、その他の機能を実装していこうかなと思っています。

スポンサードリンク

Related

Pydanticで定義したクエリパラメータをFastAPIのドキュメントに反映する
·☕4分
#テック系 #Python #FastAPI #Pydantic
miseとpoetryでPython環境構築 + miseのtask利用
·☕5分
#テック系 #mise #Python #Poetry #Streamlit #環境構築
APSchedulerを用いてFastAPIでジョブの定期実行
·☕5分
#テック系 #Python #FastAPI #APScheduler
ollamaとstreamlitでお手軽LLMアプリ構築
·☕7分
#テック系 #Python #Streamlit #Ollama #Docker