I tried my hands on streamlit building an app i seem to have an issue.
if I create button inside a button with an if statement , it does not seem to work. if just resets or restarts the app. Is there a way to fix it . Below is my code and a video of what I mean. Kindly assist
import streamlit as st
def main():
st.subheader(‘new’)
name = st.text_input(‘Enter your name’)
if st.button(‘Send’):
st.write(name)
if st.checkbox(‘bye’):
st.write(‘I see’)
if st.checkbox(‘welcome’):
st.write(‘you see’)
When I tried to run your code, I actually couldn’t get it to start at all.
But I was able to get it working, possibly as you intended it to work, just by getting rid of the if __name__=="__main__" check:
import streamlit as st
def main():
st.subheader("new")
name = st.text_input("Enter your name")
if st.button("Send"):
st.write(name)
if st.checkbox("bye"):
st.write("I see")
if st.checkbox("welcome"):
st.write("you see")
main()
Can you give that a try and let us know if that fixes the issue?
Thanks for trying out Streamlit! Please let us know how it goes.
@nthmost I believe this is related to a problem I’ve been having with streamlit, where my dashboard also refreshes whenever I change any option (checkbox, button, selectbox, etc.). Essentially, what my board does is take a query from the user, return some results from a website, run my classifier on the returned results, and displays them. The output of each classified piece of content has a button I’d like users to be able to click to give feedback (i.e. that the classification is incorrect). However, it’s non-functional when clicking the checkbox refreshes the panel and clears the display of all the comments. This is the relevant section of my code (from my main function) that triggers the classification and display of the results.
# Perform classification task
results, outputs, messages = [], [], []
if st.button("Classify"):
with st.spinner("Loading Model"):
model, tokenizer = get_model_and_tokenizer(select_model)
with st.spinner("Analyzing..."):
results = classify(texts, model, tokenizer)
outputs = [None] * len(results)
messages = [None] * len(outputs)
# Display results
for idx, res in enumerate(results):
classification = max(res['scores'], key=res['scores'].get)
output_str =f"""
### {idx+1} %s
| ? | category 1 | category 2 |
|:---:|:-----------------:|:-------------:|
|{res['scores']['?']} | {res['scores']['ct']} | {res['scores']['c2']} |
***
"""
st.markdown('----\n----')
st.markdown(res['raw'])
if classification == '?':
st.info(output_str % "Cannot determine category")
elif classification == 'not antisemitic':
st.success(output_str % "This looks like category 1 comments in my training set")
elif classification == 'antisemitic':
st.error(output_str % "This is similar to category 2 comments in my training set")
else:
raise ValueError("Unexpected classification value", classification)
if output_options['tokens']:
st.info(f"#### {current_model} Tokenization\n {res['tokens']}")
messages[idx] = st.empty()
outputs[idx] = st.checkbox(f'Mark classification as incorrect', False, idx+1)
for cb, mess in zip(outputs, messages):
if cb:
mess.markdown("### Thanks for marking this!")
save_feedback(results[idx], mess)
If there’s any easy way to fix this behavior, I would appreciate knowing what it is. I’ve already tried setting the value of the Classify button to a variable, as well as moving the loop into or out of a function call. No matter what, hitting any control or widget leads to a re-run of the entire main function, by the looks of it.
Hi @Anotar
Rerunning the entire script is the designed behavior of Streamlit. There isn’t a “official” standard method to maintain state across runs of the script in the way you want but there are at least two effective workarounds, both of which have been discussed at length in the forum and both of which work well.
One is to use the @st.cache decorator with a parameter that allows you to mutate the cache. The other is to use a SessionState object hooked into the Streamlit internals.
A search of the forum will get you more details; it’s a common topic.
The key point is that a Streamlit script doesn’t have an “entry point” like main() in the traditional Python sense. It is best to think of it as a collection of operations that the Streamlit wrapper executes for you.
Thanks @knorthover – Yes, that’s the canonical answer for now.
However, the idea that Streamlit should “save” user input so people can develop multi-path applications is becoming a popular request. As a consequence we’re talking about driving Streamlit towards an execution model that supports this.
So for the moment, yes, Streamlit refreshes the entire app whenever the engine accepts user input. With any luck, though, we’ll have stuff like per-user and per-browser-tab tracking to make it possible to develop real multiuser applications, and widget inputs that persist their input and allow you to pass on their consequences.
Thanks for bearing with us, and keep the questions and suggestions coming!
This was a very useful discussion as it clarified (for me) how Streamlit runs.
I have a similar app I’m working on, and have the same issue. Good to know you are working on it! I am finding that user widgets which don’t trigger a top to bottom rerun is essential.
I’m getting around this by setting options like:
option1, option2, usertext1 = False, False, "default_text"
if st.sidebar.checkbox("Process for xyz"):
option1 = True
# etc etc
And the main func is behind a button, this only runs when the button is pressed, even though user input reruns everything (but saves widget state). My processing func changes quite a bit (And is pretty slow) depending on the user options, so its important it doesn’t run until the user is done fiddling with options.
if st.button('Process'):
with st.spinner("Processing data..."):
df2 = process_data(df, selected_cols, option1, option2, usertext1)
st.markdown("The first 50 rows:")
st.dataframe(df2.head(50))
st.balloons()
Note: The st.ballons is probably the most important part of the app, would also appreciate a st.sparkles, st.rainbows and st.giphy("unicorns") to jazz up the app!
“However, the idea that Streamlit should “save” user input so people can develop multi-path applications is becoming a popular request. As a consequence we’re talking about driving Streamlit towards an execution model that supports this.”
Thanks, @nthmost but it didn’t work for me. It seems like when that is an if statement inside an if st.button commands, it resets. Is there a way around it?
The exact code you posted here, always reruns from the beginning no matter what…I have added a printstatement at the very top and it is always printed.
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.