コンテンツにスキップ

状態を保持する (Session State)

Streamlitを学ぶ上で、最大の壁であり、最も重要な機能が Session State(セッションステート) です。

これを使うことで、「カウンター」や「チャットアプリ」、「ログイン機能」などが作れるようになります。

Streamlitには以下の絶対的なルールがあります。

「何か操作(ボタンクリックなど)をするたびに、コードを1行目から最後まで再実行する」

このルールのせいで、普通の変数にデータを入れても、次の操作をした瞬間に変数が初期化されて消えてしまいます。

以下のコードを見てください。count = 0 と定義してボタンで +1 していますが、何度押しても 1 にしかなりません。

counter_ng.py
import streamlit as st
st.title("うまくいかないカウンター 😢")
st.write("ボタンを押すとカウントアップさせたいですが...")
# 普通の変数定義
count = 0
if st.button("カウントアップ"):
count += 1
st.metric(label="現在のカウント", value=count)
st.error("何度押しても「1」のまま増えません。なぜでしょうか?")

なぜ増えない? ボタンを押すたびにプログラムが最初から走り直し、毎回 count = 0 で変数がリセットされてしまうからです。


この「リセット」を防ぐために用意されているのが st.session_state です。 これは 「再実行されても消えない、特別な金庫」 のようなものだと考えてください。

書き方は「辞書型(Dictionary)」とほぼ同じです。

counter_ok.py
import streamlit as st
st.title("覚えているカウンター 😎")
# 1. 初期化(最初の一回だけ実行される)
# "count" というキーがまだ金庫(Session State)になければ、0を入れる
if "count" not in st.session_state:
st.session_state["count"] = 0
# 2. 値の更新
if st.button("カウントアップ"):
# 金庫の中身を取り出して +1 する
st.session_state["count"] += 1
# 3. 表示
st.metric(label="現在のカウント", value=st.session_state["count"])
st.success("再実行されても値が保持されています!")
# デバッグ用:現在保存されている全データを表示
with st.expander("Session Stateの中身を見る"):
st.write(st.session_state)

必ず以下の「初期化パターン」を使います。

# もし "key" という名前のデータがまだ金庫になければ...
if "key" not in st.session_state:
# 初期値をセットする
st.session_state["key"] = 0