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]
})
@okld
Copy link
Author

okld commented Jun 14, 2020

I'm not sure to understand under which circumstances the state is cleared. When and how do you use st.cache? Could you provide some code to reproduce the issue? It'd greatly help!

@sahil1123
Copy link

can I run this on my laptop? what would be the command?

@okld
Copy link
Author

okld commented Jun 17, 2020

if Streamlit is correctly installed on your laptop, executing streamlit run st_demo_settings.py should work.

@sahil1123
Copy link

Thanks. Could you help how this http://ml.madpowah.org:8501/ might have implemented navigation across pages.

@okld
Copy link
Author

okld commented Jun 18, 2020

If you want an example without my session state boilerplate code, you can try something like this:

import streamlit as st


def main():
    # Register your pages
    pages = {
        "First page": page_first,
        "Second page": page_second,
    }

    st.sidebar.title("App with pages")

    # Widget to select your page, you can choose between radio buttons or a selectbox
    page = st.sidebar.selectbox("Select your page", tuple(pages.keys()))
    #page = st.sidebar.radio("Select your page", tuple(pages.keys()))

    # Display the selected page with the session state
    pages[page]()


def page_first():
    st.title("This is my first page")
    # ...


def page_second():
    st.title("This is my second page")
    # ...


if __name__ == "__main__":
    main()

@coy17a
Copy link

coy17a commented Jul 15, 2020

Hello, I just want to thank you. It worked great for me.

@NBStephens
Copy link

This is perfect. Thank you!

@the-marlabs
Copy link

@Ghasel, could you suggest how to persist the session on page refresh and across duplicate tabs?
Can we use caching?
Any suggestions/possible workarounds will be appreciated.

@davins90
Copy link

davins90 commented Sep 9, 2020

Hi guys,
i try to let the code works as the one shows above, but in the for..loop cycle that i show below that doesn't work. It's seems that if the assignment with one "number_input" works, inside a loop not. Do you know why?
Thanks
image

@feliperoque
Copy link

feliperoque commented Apr 1, 2021

Hello, this alternative code is working well? @okld

@singhpratech
Copy link

You are a champ ! It worked like a charm in my App , which is a multipage app , Thanks so much _/|_

@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