Streamlit入門 – 4)Session

本記事はStreamlit入門の4回目です。セッションとは状態を保存する仕組みのことです。ボタンの操作などを行ったときにページ全体が再読み込みされ、ページ全体が再度最初から実行されます。これにより変数はすべて初期化されます。値を保存しておきたいようなときには、このような挙動が望ましくないこともあるでしょう。ここでは、セッション(session)を使って値を継続的に保持する方法について説明します。

本記事はFuture Coders独自教材からの引用です。

session_state

session_stateはStreamlitで用意されている辞書型のオブジェクトです。値を保存しておくことができます。

Session State – Streamlit Docs

以下はボタンを押下するとカウントを増やすサンプルです。

import streamlit as st

count = 0
if st.button('count'):
    count += 1

st.write(f"count={count}")
カウントの様子
Streamlit入門 – 4)Session 6

ボタンを押下するとst.buttonがTrueを返すので、countの値が1増加します。しかし、ボタンを何度おしてもカウントは1から増えることはありません。

ボタンを押すたびにページが再読み込みされ、そのたびにcountが0に初期化されてしまうためです。

ボタンを押下するたびに数値を増やすには、ページを再読み込みしても値が消えないように、値を覚えておく必要があります。Streamlitでは、session_stateというオブジェクトに値を保存することで、値を保持することが可能になります。

JavaScriptのlocalStorageをご存じの方は同じような挙動と考えると分かり易いかもしれません。

import streamlit as st

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

if st.button('count'):
    st.session_state['count'] += 1

st.write(f"count={st.session_state['count']}")

st.session_stateは辞書のようにアクセスします。キーが辞書に含まれるか否かは in や not in 演算子を使用して調べることができます。最初に、”count”というキーがない場合は、値0をセットしています。ボタンが押下されるとその値を1増やすという処理を行っています。

以下は辞書に値を登録して更新するサンプルです。Streamlitでの動作を説明するものではありません。st.session_stateの使い方が分かりづらいと感じた方は比較しながら読んでいただけるとよいでしょう。

d = {}
if "count" not in d:
    d["count"] = 0

d["count"] += 1

print(d["count"])

Pythonでは辞書は変数名[キー]のようにアクセスしますが、StreamlitではJavaScriptのように変数名 . キーと記述することも可能です。

上記のsession2.pyは以下のように書き換えても同じように動作します。

import streamlit as st

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

if st.button('count'):
    st.session_state.count += 1

st.write(f"count={st.session_state.count}")

状態を管理する変数を、最初にsession_stateから読みだして(session_stateに値があるときはそこから、ないときは初期化)、最後に書き込むような使い方も可能です。

import streamlit as st

count = st.session_state.count if "count" in st.session_state else 0

if st.button('count'):
    count += 1

st.write(f"count={count}")

st.session_state.count = count

ウィジェットとの紐づけ

このようにsession_stateを使用するとプログラムで値を保持することができるようになります。inputなどのWidgetを使うときに、入力値を保持するときにも利用できます。ウィジェットに関しては以下の記事を参照してください。

Streamlit入門 – 3)Widget – Future Coders (future-coders.net)

import streamlit as st

st.text_input('映画', key="movie_name", value="titanic")
st.write('あなたの好きな映画:', st.session_state.movie_name)

text_inputにおいて引数keyに名前を指定すると、session_stateのキー名のプロパティに値が保存されます。自分で明示的に変数に値を代入しなくても、値が保存されるので便利です。
以下はcheckboxにkey引数を指定した例です。

import streamlit as st

apple = st.checkbox('apple', key="apple_check")
orange = st.checkbox('orange', key="orange_check")
melon = st.checkbox('melon', key="melon_check")

st.write(f":{st.session_state}")
Checkbox
Streamlit入門 – 4)Session 7

チェックボックスを操作すると、session_stateの値が更新されることが確認できます。

以下はラジオボタンの例です。

import streamlit as st

st.radio("好きな食べ物は?", ('ラーメン', 'カレー', '寿司'), horizontal=True, key="food")
st.write(f"{st.session_state.food}が好きなんですね!")
session3
Streamlit入門 – 4)Session 8

演習

ex-session1.py

ボタンにkey引数を指定して、セッションにどのような値が保存されるか確認してください。

演習1
Streamlit入門 – 4)Session 9

ex-session2.py

Multiselectにkey引数を指定して、セッションにどのような値が保存されるか確認してください。

演習2
Streamlit入門 – 4)Session 10

解答例

ex-session1.py

import streamlit as st
st.button("hello", key="hello")
st.button("world", key="world")
st.write(st.session_state)

ex-session2.py

import streamlit as st
st.multiselect("好きなスポーツは?",
    ["soccer","rugby","running","swimming"],["running","swimming"],
    key="sports")
st.write(st.session_state.sports)