Streamlit設計方針: 効果的なアプリケーションの構築を考える
はじめに
初めまして。
都内IT企業で、データアルゴリズムチームのエンジニアをしております、Noraです。
機械学習やデータサイエンスプロジェクトに関わる際、デモプロダクトを作りたい状況は多いと思います。
その際、Streamlitという、PythonのみでWebアプリケーションを作成できるフレームワークが有用です。
今回の記事では、「運用保守が容易で開発コストを下げる」ディレクトリ設計方針を解説していきます。
「Streamlitプロジェクトの、最適なディレクトリ設計方針を考えたい」という、チームで開発しているエンジニアにおすすめの記事となっております!
こちらの記事内容は個人の経験がベースになっておりますので、未熟な点も多いかと思います。
ご意見あればコメントいただけますと幸いです🙆♀️ 🙆
では、ぜひご覧ください!
設計の考え方
今回、ディレクトリ設計を考える上で、以下2つのポイントを意識しています。
これらを意識することで、チーム開発の際も開発容易性が高まり、運用保守に優れたサービス開発を実現します。
1. データ処理とUIの分離
データ処理部分とUIを分離し、別ディレクトリに構成しています。
Streamlitにおいては、ページ表示UIの部分をpagesディレクトリへ配置し、データ処理の部分はservicesディレクトリに配置します。
今後、ビジネスロジックや、データモデルが発生した場合には、modelsディレクトリにモデル構造やバリデーションモデルを定義することを検討します。
2. 責務の明確化
責務とは、プログラムで処理するタスクや役割のことです。
1つの関数が複数の処理を担っていると、チームメンバーにとっての理解コストが高まると共に、関数を変更した際の副作用が大きくなり、バグの温床となってしまいます。
プログラムは必ず変更されるものという前提で、責務が明確になっているプログラムを意識しましょう。
ディレクトリ設計の個人的ベストプラクティス
上で述べた2点を意識して、小規模Webアプリケーションの設計を考えます。
今回は、「アップしたCSVデータを元に、簡単な計算をしてからグラフ描画する」というアプリケーションを作成します。
以下のディレクトリ構成をアプリケーションを実装します。
my_streamlit_app/
┗ app.py
┗ pages/
┗ dashboard.py ## ダッシュボードのページを描画する
┗ services/
┗ calculate.py ## 計算を行う
┗ file_service.py ## ファイル操作を実施する
┗ models/
┗ data_model.py ## 今回は実装しない
┗ requirements.txt
┗ .gitignore
┗ .venv ## Pythonの仮想環境を構築する
┗ ...
サンプルコードを実装する
1. Python環境のセットアップ
ファイル実装前に、まずはPythonの仮想環境を構築します。
下のコマンドを実行します。
$ python3 -m venv .venv && source .venv/bin/activate
$ pip install pandas
$ pip install streamlit
$ pip freeze
----------
[出力結果]
numpy==1.26.1
packaging==23.2
pandas==2.1.2
Pillow==10.1.0
protobuf==4.25.0
pyarrow==14.0.0
pydeck==0.8.1b0
....
コマンドを実行できたら、requirements.txtにパッケージを記載します。
pandas==2.1.2
streamlit==1.28.1
.venv以下のファイルはgit管理しないように、.gitignore
ファイルにスクリプトを追加します。
.venv/
2. servicesディレクトリで、処理部分を実装する
まずは、csvの処理を行うfile_service.py
を実装します。
正直、1行コードなので関数にしない方が良いですが、今回は便宜上ファイルに分離しています。
import pandas as pd
def read_csv(filename: str) -> pd.DataFrame:
return pd.read_csv(filename)
次に、データフレーム処理を司るファイルを作成します。
import pandas as pd
def calculate(df: pd.DataFrame, sales_column: str, tax_column: str) -> pd.DataFrame:
calc_df = df.copy()
calc_df['sales_with_tax'] = calc_df[sales_column] * calc_df[tax_column]
return calc_df
3. pagesディレクトリで、グラフ描画ページを実装する
import streamlit as st
from services import calculate, file_service
def display():
st.header("Upload CSV for Calculation")
uploaded_file = st.file_uploader("Choose a CSV file", type="csv")
if uploaded_file:
data = file_service.read_csv(uploaded_file)
calc_df = calculate.calculate(data, "sales", "tax")
st.line_chart(data=calc_df, x="date", y="sales_with_tax")
4. メインファイルを実装する
これまでに実装してきたモジュールを、メインファイル内で呼び込みます。
import streamlit as st
from pages import dashboard
def main():
st.title("CSV Data Processing and Graph Display")
dashboard.display()
if __name__ == "__main__":
main()
5. 動作確認
では、最後にstreamlitを使って、動作確認を行います。
streamlit run app.py
を実行すると、以下の画面に移ります。
CSVは以下のように「date, sales, tax」カラムの入ったデータを挿入します。
date,sales,tax
2023-01-01,10000,1.08
2023-01-02,12000,1.1
2023-01-03,13000,1.08
2023-01-04,14000,1.1
2023-01-05,12000,1.08
2023-01-06,12000,1.1
2023-01-07,16000,1.08
2023-01-08,24000,1.1
2023-01-09,19000,1.08
以下のように、無事グラフが描画されました!🎉
あと書き
記事をお読みいただき、ありがとうございました。
今回はStreamlitプロジェクトにおける、ディレクトリ設計について解説してきました。
一つのファイルにベタ書きするよりも、適切な設計に沿った開発を行うことで、個人だけでなくチームにとっても、良い開発体制を整えることができると感じました。
今後も皆さんに有益な情報を届けたいと思っております。
もし補足点・修正等ございましたら、ご気軽にコメントいただけますと幸いです。
では、失礼いたします!
参考文献
Discussion