Skip to content

Instantly share code, notes, and snippets.

@okld
Last active September 25, 2023 13:50
Show Gist options
  • Star 61 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save okld/0aba4869ba6fdc8d49132e6974e2e662 to your computer and use it in GitHub Desktop.
Save okld/0aba4869ba6fdc8d49132e6974e2e662 to your computer and use it in GitHub Desktop.
Streamlit - Settings page with session state
import streamlit as st
from persist import persist, load_widget_state
def main():
if "page" not in st.session_state:
# Initialize session state.
st.session_state.update({
# Default page.
"page": "home",
# Radio, selectbox and multiselect options.
"options": ["Hello", "Everyone", "Happy", "Streamlit-ing"],
# Default widget values.
"text": "",
"slider": 0,
"checkbox": False,
"radio": "Hello",
"selectbox": "Hello",
"multiselect": ["Hello", "Everyone"],
})
page = st.sidebar.radio("Select your page", tuple(PAGES.keys()), format_func=str.capitalize)
PAGES[page]()
def page_home():
st.write(
f"""
Settings values
---------------
- **Input**: {st.session_state.text}
- **Slider**: `{st.session_state.slider}`
- **Checkbox**: `{st.session_state.checkbox}`
- **Radio**: {st.session_state.radio}
- **Selectbox**: {st.session_state.selectbox}
- **Multiselect**: {", ".join(st.session_state.multiselect)}
"""
)
def page_settings():
st.header("Change settings")
st.text_input("Input", key=persist("text"))
st.slider("Slider", 0, 10, key=persist("slider"))
st.checkbox("Checkbox", key=persist("checkbox"))
st.radio("Radio", st.session_state["options"], key=persist("radio"))
st.selectbox("Selectbox", st.session_state["options"], key=persist("selectbox"))
st.multiselect("Multiselect", st.session_state["options"], key=persist("multiselect"))
PAGES = {
"home": page_home,
"settings": page_settings,
}
if __name__ == "__main__":
load_widget_state()
main()
from streamlit import session_state as _state
_PERSIST_STATE_KEY = f"{__name__}_PERSIST"
def persist(key: str) -> str:
"""Mark widget state as persistent."""
if _PERSIST_STATE_KEY not in _state:
_state[_PERSIST_STATE_KEY] = set()
_state[_PERSIST_STATE_KEY].add(key)
return key
def load_widget_state():
"""Load persistent widget state."""
if _PERSIST_STATE_KEY in _state:
_state.update({
key: value
for key, value in _state.items()
if key in _state[_PERSIST_STATE_KEY]
})
@bbokka123
Copy link

hello is there any way to set session-timeout which close the session after certain period???

@okld
Copy link
Author

okld commented Jun 16, 2021

@bbokka123, you can initialize your session state with the current time, and then each time the script reruns, get the new current time and compare it with the one stored in your state. If it exceeds your period, you can use st.stop() to stop your script execution.

@okld
Copy link
Author

okld commented Jul 2, 2021

@abhisheksms
Copy link

Streamlit 0.84.0 has introduced a brand new session state feature

Hi! is there any code snippet similar to the current gist, which demonstrates detailed usage of st.session_state Thanks!

@okld
Copy link
Author

okld commented Sep 14, 2021

Hello @drupano, I updated this gist to use st.session_state intsead of the old custom implementation.

@CharlyWargnier
Copy link

Thanks Synode!

@bbokka123
Copy link

@bbokka123, you can initialize your session state with the current time, and then each time the script reruns, get the new current time and compare it with the one stored in your state. If it exceeds your period, you can use st.stop() to stop your script execution.

thanks!! one more question ... is there any way to get event when the script reruns? just like notifications if the script reruns

@steeley
Copy link

steeley commented Nov 19, 2021

Seems the new session state stuff has broken this. In fact I cannot see any way to have page persistence with multiple pages in Streamlit.

@federicodecillia
Copy link

The code doesn't work in streamlit 1.4.0.
When I switch the first time from "Settings" to "Home" page it works, but then going back to "Settings" it resets all value to default.

@okld
Copy link
Author

okld commented Jan 30, 2022

Hello @steeley and @federicodecillia, I updated the gist to fix this issue.

Apparently if a widget bound to session state (with key param) is displayed in run #1, but not in run #2, the associated session state variable is cleared in run #3. Self-applying session state values seems to do the trick.

@steeley
Copy link

steeley commented Jan 30, 2022

thanks will have a go and see how it works.

@federicodecillia
Copy link

Thanks @okld ! Now it works!

@okld
Copy link
Author

okld commented Jan 31, 2022

Apparently if a widget bound to session state (with key param) is displayed in run #1, but not in run #2, the associated session state variable is cleared in run #3. Self-applying session state values seems to do the trick.

Session state behavior changed in Streamlit 0.89.0. Related issue: streamlit/streamlit#4338

@roman-kouzmenko
Copy link

Many thanks for this snippet, it helped me work around #4338.
When I try the code however, on first page load, the widgets are initialized to default values rather than the initial values in the session state.
Does the same happen fo you? Is there any workaround?

@nvelamuri0656
Copy link

Hi All,

I am new to streamlit,trying to build multipage webapp.
In first page i will upload a file and click and button and it redirects to second page.
In second page i have side bar and radio buttons. Based on button selection the output need to be changed.
If i change radio button multiple times i am facing EOF ran of input error could you please help me

@Jacobrsmith37
Copy link

Thanks for this! Works great for me.

I'm trying to edit the code so that I can persist a session state of an editable dataframe while navigating between different pages of the app. I'm using AgGrid to make the df editable, but when refreshing or going to another page, the df defaults back to original values. Do you have any suggestions on how to implement this from your code above? I've been stuck on this for a week now

@lluissalord
Copy link

@okld Really nice work. However, I see that for refreshing is not working anymore. Do you have any idea of how to handle it?

@EqualAPriori
Copy link

Really neat concept! Does this only work if you have a main script registering and driving the different pages?

I tried this persist/load_widget_state() approach on a multi-page app using the current directory structure of implementing multipage apps, and it didn't work for me.

@Stachys
Copy link

Stachys commented Sep 25, 2023

Hey man, many thanks for this snippet!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment