HI Streamlit community,
I have a question:
So I want to run a pretty large analysis via a Streamlit based GUI, and I now want to disable the users from changing any variables during the analysis, but after the analysis is done it should lift the disabling of the interactive elements.
import streamlit as stimport time
if "disabled" not in st.session_state:st.session_state.disabled = False
def disable():
st.session_state.disabled = True
def enable():
st.session_state.disabled = False
st.button("Run process",disabled=st.session_state.disabled,on_click=disable)
#Whatever process takes placetime.sleep(10)
st.toast("done")
#now set the session state back to False
Because just adding the enable function at the end does update the variable but not the rendering like it does on the on_click from the st.button. So is there a way to update the rendering of what is disabled and what is enabled again?
import streamlit as st
import time
if "disabled" not in st.session_state:
st.session_state.disabled = False
if "run_requested" not in st.session_state:
st.session_state.run_requested = False
def start_run():
st.session_state.disabled = True
st.session_state.run_requested = True
st.button(
"Run process",
disabled=st.session_state.disabled,
on_click=start_run
)
if st.session_state.run_requested:
st.toast("process")
st.session_state.run_requested = False
time.sleep(10)
st.toast("done")
st.session_state.disabled = False
st.rerun()
I considered something like this, but this reruns and does not keep the “done” toast or other instance specific outputs. And as I understand, after the rerun you can’t just add the toast there because the rerun stops further code processing. Anyone got any ideas?
Hey, thanks for your thoughtful question and for sharing your code!
You’re right: simply setting st.session_state.disabled = False at the end of your process won’t immediately re-enable widgets, because Streamlit only updates widget states on rerun. Using st.rerun() after your process does reset the UI, but it also clears transient outputs like st.toast() since the script restarts from the top and doesn’t “remember” the toast.
The recommended approach is to save any outputs you want to persist (like a “done” message) in st.session_state, then display them after rerun. For example, set a flag like st.session_state.show_done = True before calling st.rerun(), and then conditionally show the toast at the top of your script if that flag is set. This way, the UI updates and your message persists for at least one rerun cycle. See the code below for a pattern that works well:
import streamlit as st
import time
if "disabled" not in st.session_state:
st.session_state.disabled = False
if "run_requested" not in st.session_state:
st.session_state.run_requested = False
if "show_done" not in st.session_state:
st.session_state.show_done = False
def start_run():
st.session_state.disabled = True
st.session_state.run_requested = True
st.button(
"Run process",
disabled=st.session_state.disabled,
on_click=start_run
)
if st.session_state.run_requested:
# Simulate long process
time.sleep(10)
st.session_state.run_requested = False
st.session_state.disabled = False
st.session_state.show_done = True
st.rerun()
if st.session_state.show_done:
st.toast("done")
st.session_state.show_done = False
This pattern ensures widgets are disabled during processing, re-enabled after, and your “done” message appears after rerun. For more details and variations, see this forum thread and this related discussion. If you run into issues, please share a minimum reproducible example and let the community jump in!
Sources:
Hey,
That is indeed a fix for my problem! Thank you very much for your response and I wish you a good rest of your day!