Mvd*_*vdD 9 python session-state streamlit
我正在构建 Streamlit 多页面应用程序,但在页面之间切换时保持会话状态时遇到问题。我的主页称为 mainpage.py ,内容如下:
import streamlit as st
if "multi_select" not in st.session_state:
st.session_state["multi_select"] = ["abc", "xyz"]
if "select_slider" not in st.session_state:
st.session_state["select_slider"] = ("1", "10")
if "text_inp" not in st.session_state:
st.session_state["text_inp"] = ""
st.sidebar.multiselect(
"multiselect",
["abc", "xyz"],
key="multi_select",
default=st.session_state["multi_select"],
)
st.sidebar.select_slider(
"number range",
options=[str(n) for n in range(1, 11)],
key="select_slider",
value=st.session_state["select_slider"],
)
st.sidebar.text_input("Text:", key="text_inp")
for v in st.session_state:
st.write(v, st.session_state[v])
Run Code Online (Sandbox Code Playgroud)
接下来,我在名为“pages”的子目录中有另一个名为“anotherpage.py”的页面,其内容如下:
import streamlit as st
for v in st.session_state:
st.write(v, st.session_state[v])
Run Code Online (Sandbox Code Playgroud)
如果我运行此应用程序,更改控件的值并切换到其他页面,我会看到控件的值被保留并打印。但是,如果我切换回主页,所有内容都会重置为原始值。由于某种原因st.session_state被清除。
有人知道如何将值保持在会话状态吗?我正在使用 Python3.11.1和 Streamlit1.16.0
小智 5
首先,了解小部件的生命周期很重要。当您为小部件分配一个键时,只要该小部件未呈现,该键就会从会话状态中删除。如果小部件有条件地不在同一页面上或通过切换页面呈现,则可能会发生这种情况。
您在第二页上看到的是小部件清理过程完成之前上一页剩余的值。在加载“另一页”结束时,Streamlit 意识到它在会话状态中的键分配给了已经消失的小部件,因此将其删除。
有两种方法可以解决这个问题。
st.session_state.my_widget_key = st.session_state.my_widget_key
Run Code Online (Sandbox Code Playgroud)
这将中断小部件清理过程并防止键被删除。但是,它需要位于您离开小部件时访问的页面上。因此,它需要出现在所有页面上。
import streamlit as st
if "multi_select" not in st.session_state:
st.session_state["multi_select"] = ["abc", "xyz"]
if "select_slider" not in st.session_state:
st.session_state["select_slider"] = ("1","10")
if "text_inp" not in st.session_state:
st.session_state["text_inp"] = ""
def keep(key):
# Copy from temporary widget key to permanent key
st.session_state[key] = st.session_state['_'+key]
def unkeep(key):
# Copy from permanent key to temporary widget key
st.session_state['_'+key] = st.session_state[key]
unkeep("multi_select")
st.sidebar.multiselect(
"multiselect",
["abc", "xyz"],
key="_multi_select",
on_change=keep,
args=['multi_select']
)
# This is a edge case and possibly a bug. See explanation.
st.sidebar.select_slider(
"number range",
options=[str(n) for n in range(1, 11)],
value = st.session_state.select_slider,
key="_select_slider",
on_change=keep,
args=["select_slider"]
)
unkeep("text_inp")
st.sidebar.text_input("Text:", key="_text_inp", on_change=keep, args=["text_inp"])
for v in st.session_state:
st.write(v, st.session_state[v])
Run Code Online (Sandbox Code Playgroud)
您会发现我对选择滑块做了不同的操作。看来需要value专门将一个元组传递给 kwarg,以确保它初始化为范围滑块。如果使用单个值而不是范围值初始化它,我就不需要更改逻辑。对于其他小部件,您可以看到默认值已被删除,有利于通过会话状态中的键直接控制它们的值。
当您执行更改小部件默认值的操作时需要小心。对默认值的更改会创建一个“新小部件”。如果您通过其键同时更改默认值和实际值,则可能会出现一些细微的行为,例如在发生冲突时出现初始化警告。