【Streamlit】ページ構成が多いアプリでの状態管理戦略(状態設計のベストプラクティス)

Streamlit、st.session_satateマルチページAPP状態管理 Streamlit
この記事は約10分で読めます。

こんにちは、JS2IIUです。
今回もst.session_stateを有効活用する事例の紹介です。複数ページのStreamlitアプリでの活用方法を事例とともに詳しくみていきます。今回もよろしくお願いします。

1. はじめに

Streamlitで複数のページを持つアプリケーションを構築する場合、ページ間で共有したい情報や、ページごとに管理したい設定項目など、”状態”(State)をどのように扱うかが重要になります。本記事では、状態管理の基本から、ベストプラクティスとなる命名ルールや状態構造の設計までを、具体的なコード例を交えてわかりやすく解説します。

2. Streamlitの状態管理の基本

Streamlitでは、st.session_stateを使うことで、ユーザーのセッションごとに変数を保持できます。これを活用することで、あるページで設定した値を別のページで再利用することが可能になります。

Python
import streamlit as st

if 'counter' not in st.session_state:
    st.session_state.counter = 0

if st.button('カウントアップ'):
    st.session_state.counter += 1

st.write(f"カウント: {st.session_state.counter}")

このコードでは、ボタンを押すたびにカウントが1ずつ増えます。このように、st.session_stateは状態を保持するための辞書として使います。

3. 状態設計の失敗例と課題

マルチページアプリでは、以下のような課題が起こりやすいです:

  • session_stateのキー名が被る(たとえば、複数ページで同じ"input"というキーを使ってしまう)
  • どのキーがどのページで使われているかわかりづらくなる
  • グローバルで使いたい状態と、ページ固有の状態が混在し管理が難しくなる

これらの問題を避けるために、次のようなベストプラクティスを導入しましょう。

4. ベストプラクティス①:キー設計のルールを決める

状態の管理をわかりやすくするために、キー名にプレフィックスをつけることをおすすめします。

🔹 命名ルールの例:

  • グローバルな状態:global_ をプレフィックスに
  • ページ固有の状態:page名_変数名 の形式

❌ 悪い例:

Python
st.session_state['input'] = "abc"

✅ 良い例:

Python
st.session_state['page_home_input_text'] = "abc"

このように明確な命名ルールを設けることで、後から見返したときや、チームでの開発でも混乱を避けることができます。

5. ベストプラクティス②:状態の分類と依存関係の整理

状態を次の2つに分類して設計すると、構造が明確になります:

  • グローバル状態:ユーザー情報や共通設定など、どのページからも参照する状態
  • ローカル状態:特定のページでのみ使用する一時的な状態

🧩 状態依存の例

以下は、3ページ構成のアプリにおける状態設計の例です:

ページ名使用する状態キー名分類
homepage_home_usernameローカル
settingsglobal_user_configグローバル
analysispage_analysis_selected_featuresローカル

6. ベストプラクティス③:状態初期化とクリア

状態の初期化を確実に行うことで、アプリの動作が安定します。

Python
# 初期化パターン
if 'page_home_username' not in st.session_state:
    st.session_state.page_home_username = ""

また、状態のリセットは以下のように個別に削除するのが安全です:

Python
# 特定キーのみ削除
if 'page_home_username' in st.session_state:
    del st.session_state['page_home_username']

7. 状態設計テンプレート(共通関数化)

状態の初期化や取得を関数化すると、コードが整理されます:

Python
def init_state():
    st.session_state.setdefault('global_user_config', {})
    st.session_state.setdefault('page_home_username', '')
    st.session_state.setdefault('page_analysis_selected_features', [])

init_state()  # 各ページで最初に呼び出す

8. ケーススタディ:3ページ構成のアプリ

Streamlitのマルチページアプリ構成で、以下のように状態管理を実装できます。

マルチページアプリについてはこちらの記事をご覧ください。

メインページ

今回のマルチページの事例は以下のファイル構成となっています。

Python
.
├── app_main.py
└── pages
    ├── home.py
    ├── settings.py
    └── analysis.py

メインページのコードは以下のとおり。

Python
import streamlit as st
st.write("This is the main app page.")

📄 ページ1: Home

Python
# pages/home.py
import streamlit as st

def home():
    if 'page_home_username' not in st.session_state:
        st.session_state.page_home_username = ""

    username = st.text_input("ユーザー名", value=st.session_state.page_home_username)
    st.session_state.page_home_username = username

    st.write(f"ようこそ、{username}さん!")

home()

⚙️ ページ2: Settings

Python
# pages/settings.py
import streamlit as st

def settings():
    if 'global_user_config' not in st.session_state:
        st.session_state.global_user_config = {'theme': 'light'}

    theme = st.selectbox("テーマを選択", ['light', 'dark'],
                         index=['light', 'dark'].index(st.session_state.global_user_config['theme']))

    st.session_state.global_user_config['theme'] = theme
    st.write(f"現在のテーマ: {theme}")

settings()

📊 ページ3: Analysis

Python
# pages/analysis.py
import streamlit as st

def analysis():
    if 'page_analysis_selected_features' not in st.session_state:
        st.session_state.page_analysis_selected_features = []

    features = st.multiselect("分析対象の特徴量を選択", ['A', 'B', 'C'],
                               default=st.session_state.page_analysis_selected_features)

    st.session_state.page_analysis_selected_features = features
    st.write(f"選択中の特徴量: {features}")

analysis()

動作の様子

9. まとめ

  • Streamlitのst.session_stateを活用することで、ページをまたいだ状態管理が可能になります。
  • プレフィックスを用いた命名ルールや状態の分類を行うことで、複雑なアプリでも状態が整理しやすくなります。
  • 初期化やクリア処理を丁寧に行うことも、安定したアプリ動作には欠かせません。

アプリの規模が大きくなるほど、状態管理の設計力が求められます。今回のベストプラクティスを参考に、わかりやすく保守しやすいアプリを目指しましょう。

🔗 参考リンク

最後まで読んでいただきありがとうございます。

コメント

タイトルとURLをコピーしました