【Streamlit】Session Stateで変数の値を保持する

Streamlit、st.session_state変数の値を保持する Streamlit
この記事は約10分で読めます。

こんにちは、JS2IIUです。
Streamlitを使ってアプリケーションを作っていると、「ボタンをクリックしたはずなのに、値がリセットされる」「ページを更新すると入力内容が消える」といった経験をしたことはありませんか?
これは、Streamlitの特性としてスクリプト全体が毎回実行されるためです。この問題を解決するのが、今回ご紹介する st.session_state です。
この機能を使えば、ユーザーの操作に応じた変数の値をセッションごとに保持することができます。今回もよろしくお願いします。

st.session_stateとは?

st.session_stateは、ユーザーごとの状態(State)を記録する辞書のようなオブジェクトです。セッションとは「ユーザーがページを開いてから閉じるまでの間」を指します。

この機能を使うことで、以下のようなことが可能になります:

  • ページの更新後も変数の値を保持する
  • ボタンを何度クリックしても、前回の値を覚えている
  • 複数のページ間で状態を共有する

st.session_stateがないと困ること

例えば、以下のようなコードを考えてみましょう。

Python
import streamlit as st

count = 0

if st.button("カウントアップ"):
    count += 1

st.write("現在のカウント:", count)

このコードでは、ボタンをクリックしても毎回カウントは「1」に戻ってしまいます。なぜなら、スクリプトが毎回ゼロから実行されるためです。

st.session_stateの基本的な使い方

この問題を解決するには、st.session_stateを使って値を保持します。

🔰 ステップ1:初期化

まず、セッション状態に変数がなければ初期化します。

Python
if 'count' not in st.session_state:
    st.session_state.count = 0

🛎️ ステップ2:ボタンのクリックで変数を更新

Python
if st.button("カウントアップ"):
    st.session_state.count += 1

📋 ステップ3:現在の値を表示

Python
st.write("現在のカウント:", st.session_state.count)

✅ 完全なコード

Python
import streamlit as st

# セッション状態の初期化
if 'count' not in st.session_state:
    st.session_state.count = 0

# ボタンをクリックするとカウントアップ
if st.button("カウントアップ"):
    st.session_state.count += 1

# 現在のカウントを表示
st.write("現在のカウント:", st.session_state.count)

実践事例①:ページの再読み込みで値を保持する

フォーム入力などで、再読み込みしても入力を残したい場合に便利です。

Python
import streamlit as st

# セッションに値がなければ初期化
if 'text' not in st.session_state:
    st.session_state.text = ""

# テキスト入力
st.session_state.text = st.text_input("名前を入力してください", st.session_state.text)

# 入力内容を表示
st.write("こんにちは、", st.session_state.text, "さん!")

実践事例②:ボタンのクリック回数をカウントする

先ほどの例を少しアレンジして、リセット機能も追加してみましょう。

Python
import streamlit as st

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

col1, col2 = st.columns(2)

with col1:
    if st.button("+1"):
        st.session_state.count += 1

with col2:
    if st.button("リセット"):
        st.session_state.count = 0

st.write("カウント値:", st.session_state.count)

実践事例③:複数ページ間で状態を共有する

Streamlitはマルチページ構成にも対応していますが、st.session_stateを使えばページ間で状態を共有することができます。

🗂️ Home.py

Python
import streamlit as st

if 'user_name' not in st.session_state:
    st.session_state.user_name = ""

st.session_state.user_name = st.text_input("あなたの名前", st.session_state.user_name)

📄 Page2.py

Python
import streamlit as st

st.write("ようこそ、", st.session_state.get("user_name", "ゲスト"), "さん!")

実践事例④:フォーム入力内容を一時保存する

「送信ボタンを押すまで入力を保持したい」といったケースにも役立ちます。

Python
import streamlit as st

if 'form_data' not in st.session_state:
    st.session_state.form_data = {"email": "", "message": ""}

with st.form("contact_form"):
    st.session_state.form_data["email"] = st.text_input("メールアドレス", st.session_state.form_data["email"])
    st.session_state.form_data["message"] = st.text_area("お問い合わせ内容", st.session_state.form_data["message"])
    submitted = st.form_submit_button("送信")

if submitted:
    st.success("送信が完了しました!")
    st.write("内容:", st.session_state.form_data)

よくあるエラーと対処法

エラー原因対処法
AttributeError: 'count'変数が初期化されていない'count' not in st.session_state で初期化
値が保持されない値を直接変数に保存しているst.session_state["key"] = 値の形式を使う
値が突然消えるセッションが切れたキャッシュやCookieの影響、再起動の可能性あり

まとめ

  • st.session_stateを使えば、Streamlitの「スクリプト全再実行」の制約を回避できる
  • 初期化 → 操作 → 表示の流れで使うのが基本
  • フォームやナビゲーションなど、実際のアプリ開発において非常に有用

参考リンク

当ブログのst.session_stateに関連する記事も参考にしてください。色々な角度での記事を書いています。よろしくお願いします。

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

コメント

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