Have been using Streamlit for a few weeks and am really loving it.
I’ve built an app that performs 10-20s of computation, displaying output as it goes. Once it comes to the end, I would like it to ask the user if they want to see additional information.
The idea is that this would be a button which, upon being clicked, would proceed to load more information and display it. Think something like this:
st.write("Doing stuff on every page load")
...
st.write("Finished doing stuff")
if st.button("Do you want to see more?"):
st.write("Doing more optional stuff")
My issue right now is that when the user presses the button, the entire page reloads. I understand why this is the case given Streamlit’s execution flow, and I understand why it makes sense.
My question is if there’s a way around this? I have seen sporadic mentions of the session_state but I don’t see how that answer applies to this case, since I’m not interested in saving information between runs. Sure, I could memoize the entire rest of the page but that’s not ideal either, as I’d have to make an artbitrary decision on the TTL. Also, there are definitely things in the app that cannot be pickled right now.
Although session state seems like it might not apply in this case it does. What you want to do is use the button to add or change a value that you hold in state, and you will use this value to display your optional information!!!
(another work around for this is actually the expander, I will mock up an example of each)
import streamlit as st
col1,buff, col2 =st.columns([2,.3,2])
with col1:
st.subheader("Expander example")
st.write("""Doing stuff on every page load
...
Finished doing stuff""")
with st.expander("Do you want to see more?"):
st.write("Doing more optional stuff")
with col2:
if "more_stuff" not in st.session_state:
st.session_state.more_stuff = False
st.subheader("Button example")
st.write("""Doing stuff on every page load
...
Finished doing stuff""")
click = st.button("Do you want to see more?")
if click:
st.session_state.more_stuff = True
if st.session_state.more_stuff:
st.write("Doing more optional stuff")
Hi Marisa - thanks for getting back to me. Unfortunately, your example isn’t a solution to my problem - I took your code, added a spinner with a sleep to it at the top of the page and found that clicking the “Do you want to see more?” button did indeed re-trigger that spinner.
The expander isn’t a solution either, since that requires the content within the expander to be run regardless of whether you’ve expanded it or not.
So, let me be clear, the Streamlit execution flow will always work like this. Each time you interact with a widget on the page the entire Streamlit script will be re-run from top to bottom.
The button solution I provided allows you to “hide” additional widgets behind a button click. Normally, when you have a button it returns True on only one run-through of the app and then changes back to its default (False). But the method I coded for you above, allows you to link a value in st.session_state that you can use instead of the return value of the button itself to run additional “stuff” in your app that will persist past the button’s natural true-only-once behaviour.
To get this method execution to work with your spinner you will likely need to add some logic to your spinner for various conditions for your app. But I won’t be able to code any examples for you until I see a minimum working example of the execution flow you’re trying to achieve.
But could you give me a few more details about what you are doing in your app (i.e. the “10-20s of computation, displaying output as it goes”)? We are currently looking at how we can improve caching, so this would be really useful feedback for me!! If you can’t share publicly, we can also write via DM or jump on a short call if you like
Re-running the application on each button click is pretty much unavoidable. If that is making your application slow, the solution is caching, either using cache primitives or session_state.
Hi! I’m also running into this exact same issue & would love help!
I’m working on an app where a user inputs a prompt:
the response dataframe is displayed, and I want them to be able to edit this dataframe response using st.dataeditor, and the edited dataframe is stored as a variable and then the same function continues with the user’s edited dataframe as a part of its new information.
Then, it returns another ‘in between step’ dataframe that the user can edit, that is again used in the rest of the function, until it finally creates the final, downloadable CSV for the user!
That sounds extremely vague so I’m also happy to DM or hop on a quick call if this hasn’t been figured out yet. Or happy to hear any advice if anyone has it.
Thank you for all your time and help in making streamlit, I’m such a huge fan streamlit is literally my favourite thing on the web right now. I’m making so many useful apps with it.
Also, the notion pages on this website are not public (or maybe its just me haha in which case I am so sorry but it keeps saying I don’t have access when I login with my notion) just in case theres more documentation there.
I tried to use caching but it did not work. My app reads a CSV input, and returns a CSV output.
@st.cache_data(persist=True)
def convert_df(df):
# IMPORTANT: Cache the conversion to prevent computation on every rerun
return df.to_csv().encode('utf-8')
csv = convert_df(df)
I would appreciate any help, I’ve been working on this for like a week and I’ve got to present it in a few days
Thanks for stopping by! We use cookies to help us understand how you interact with our website.
By clicking “Accept all”, you consent to our use of cookies. For more information, please see our privacy policy.
Cookie settings
Strictly necessary cookies
These cookies are necessary for the website to function and cannot be switched off. They are usually only set in response to actions made by you which amount to a request for services, such as setting your privacy preferences, logging in or filling in forms.
Performance cookies
These cookies allow us to count visits and traffic sources so we can measure and improve the performance of our site. They help us understand how visitors move around the site and which pages are most frequently visited.
Functional cookies
These cookies are used to record your choices and settings, maintain your preferences over time and recognize you when you return to our website. These cookies help us to personalize our content for you and remember your preferences.
Targeting cookies
These cookies may be deployed to our site by our advertising partners to build a profile of your interest and provide you with content that is relevant to you, including showing you relevant ads on other websites.