こんにちは、JS2IIUです。
個人的にはあまり好きではないのですが、WEB上で名前やメールアドレスだけでなく住所や名前の振り仮名など、わざわざ入力させるサイトが日本には多いと思います。ユーザ体験をさらに悪化させないための方法について考えてみたいと思います。今回もよろしくお願いします。
はじめに
Streamlit を使って Web アプリケーションを構築していると、「ページを再読込したら状態がリセットされた」「一定時間放置したら入力した内容が消えていた」という経験をされた方も多いのではないでしょうか。
これは Streamlit におけるセッションの切断が原因であり、内部的には st.session_state が初期化された状態で再構築されているためです。
本記事では、Streamlit のセッション管理の仕組みとセッションタイムアウトのリスクについて技術的に丁寧に解説し、状態を保持・復元するための実践的な方法を具体的なコードとともに紹介します。
Streamlit における「セッション」とは?
Streamlit アプリは、ユーザーごとに独立した「セッション(Session)」という単位で実行されます。ユーザーが Web ブラウザでアプリにアクセスした瞬間にセッションが開始され、ボタンの操作や入力の変更があるたびに、そのセッションのスクリプトが再実行されます。
st.session_state の役割
Streamlit の st.session_state は、セッションごとの状態(state)を保持するためのオブジェクトです。これは辞書(dict)型のインターフェースを持ち、ユーザー操作によって変化する変数を格納するのに使われます。
使用例
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}")このように st.session_state を使えば、ボタンをクリックしても値がリセットされることなく、セッション中は状態を維持することができます。
セッションが切れる条件とは?
Streamlit のセッションは以下の状況で終了(タイムアウト)する可能性があります。
| 条件 | 説明 |
|---|---|
| ブラウザの再読込 | ブラウザで F5 キーや更新ボタンを押すと、新しいセッションが作成されます |
| 一定時間の無操作 | デフォルトでは 15 分間ユーザー操作がないとセッションが自動終了します(変更不可) |
| 通信切断 | ネットワーク接続の断絶や VPN 切り替えなどによりセッションが切れることがあります |
セッションが切れると、アプリは「新しいセッション」として再構築され、st.session_state の内容は初期化されます。つまり、保持していた入力内容や変数は失われるのです。
セッションタイムアウトで何が起こるか?
以下のコードで具体的な挙動を確認してみましょう。
import streamlit as st
if "name" not in st.session_state:
st.session_state.name = ""
st.text_input("名前を入力してください", key="name")
st.write(f"こんにちは、{st.session_state.name} さん!")このアプリでは、ユーザーがテキストボックスに名前を入力すると、その内容が st.session_state["name"] に格納されます。しかし、ブラウザを再読込するとセッションがリセットされ、st.session_state["name"] は初期値である "" に戻ってしまいます。
このように、セッションが切れるとすべての状態がリセットされるという点は、フォーム入力や一時データの保持が重要なアプリでは重大な問題になり得ます。
状態の保持と復元の実践的アプローチ
セッションタイムアウトに備えるには、セッション外に状態を保存し、セッション再開時にそれを復元する仕組みを実装する必要があります。
✅ 方法1:状態を JSON ファイルに保存する
簡易的で扱いやすい方法として、状態をローカルファイル(JSON)に保存する例を紹介します。
ステップ① 状態を読み込む関数
import json
import os
def load_state():
if os.path.exists("session_data.json"):
with open("session_data.json", "r") as f:
return json.load(f)
return {"counter": 0}ステップ② 状態を保存する関数
def save_state(state):
with open("session_data.json", "w") as f:
json.dump(state, f)ステップ③ Streamlit アプリに適用
import streamlit as st
# 初期化(セッション開始時のみ)
if "counter" not in st.session_state:
state = load_state()
st.session_state.counter = state["counter"]
# イベント処理
if st.button("カウントアップ"):
st.session_state.counter += 1
save_state({"counter": st.session_state.counter})
# 表示
st.write(f"現在のカウント: {st.session_state.counter}")このように、セッションが切れても状態が JSON ファイルに保存されているため、次回アクセス時に復元することができます。
状況別:セッション切断時の対処法
📌 ケース1:ブラウザ再読込
問題点:F5 キーや再読込ボタンを押すと、セッションが新しくなり、入力済みの情報が消える。
対処法:
- 重要なデータは
st.session_stateのみに依存せず、明示的に保存処理を行う。 - 保存先としては、ファイル、SQLite、Redis、S3 などアプリの性質に応じて選択。
📌 ケース2:一定時間放置によるタイムアウト
問題点:ユーザーがフォーム入力中にしばらく操作をしないと、セッションが切れてしまい状態がリセットされる。
対処法:
- 自動保存処理を導入し、タイムアウト前に状態を記録する。
st_autorefreshやst.empty()を活用し、非表示の更新を定期実行することでセッションの延命が可能。
📌 ケース3:ネットワーク切断
問題点:一時的な通信切断や VPN の切替によってセッションが切れる場合がある。
対処法:
- ネットワークに依存しない状態管理設計を行う。
- ローカルやクラウドストレージへの非同期保存処理でフェールセーフを確保する。
セッション維持・復元のテクニック
1. st_autorefresh による自動再描画
Streamlit 公式の st_autorefresh を使うことで、一定間隔でアプリを自動リロードし、セッションを延命できます。
from streamlit_autorefresh import st_autorefresh
# 30秒ごとに再描画(セッション維持目的)
st_autorefresh(interval=30 * 1000, key="autorefresh")こちらの記事も参考になります。
Automatically refresh page – Using Streamlit – Streamlit
2. セッション ID を使った個別管理(応用)
ユーザーのセッションごとに一意な ID を割り当てて状態を管理することで、複数ユーザーに対応した状態保存が可能です。これはより高度な実装になりますが、本格的なアプリでは推奨されます。
まとめ
| 内容 | 説明 |
|---|---|
| セッションとは | ユーザーごとの Streamlit スクリプト実行単位であり、st.session_state によって状態を管理 |
| セッション終了条件 | 再読込・放置・通信断などでセッションは終了し、状態がリセットされる |
| 状態維持の工夫 | 状態を外部ファイルやデータベースに保存し、セッション切断後に復元する |
| セッション延命策 | 定期的な非表示描画や st_autorefresh による自動更新処理 |
セッションの仕組みを正しく理解し、適切に状態を保持・復元できるように設計することで、ユーザーにとって信頼性の高いアプリケーションを構築することができます。
参考リンク
本ブログのst.session_stateに関連する記事も参考にしてみてください!
- 【Streamlit】st.session_stateの初期化を関数化して整理する方法 | アマチュア無線局JS2IIU
- 【Streamlit】st.session_state とコールバック関数の活用方法 | アマチュア無線局JS2IIU
- 【Streamlit】st.session_state.clear() による状態のリセット操作 | アマチュア無線局JS2IIU
- 【Streamlit】st.session_state に辞書・リストなどの複雑なオブジェクトを持たせる方法と実践例 | アマチュア無線局JS2IIU
- 【Streamlit】st.session_state でフラグ制御と一時的なUI操作を管理する | アマチュア無線局JS2IIU
- 【Streamlit】セッションごとにユニークなIDや一意の情報を持たせる | アマチュア無線局JS2IIU
- 【Streamlit】st.session_stateの内容を開発中にデバッグ表示する方法 | アマチュア無線局JS2IIU
- 【Streamlit】ページ構成が多いアプリでの状態管理戦略(状態設計のベストプラクティス) | アマチュア無線局JS2IIU
最後まで読んでいただきありがとうございました。

