Is there a way to temporarily disable streamlit app rerun?
I have a function that takes a couple minutes to finish (waiting for OpenAI API). The function is nested in st.spinner, but whenever a user clicks something in the UI while waiting for the function to complete (edit), the app is rerun and the function is triggered again, causing multiple identical requests to OpenAI API.
I have read the attached post but the answer does not solve my use case (try adding the button above the spinner).
It would be nice if st.spinner has an option disable_rerun, or am I missing something?
Hello,
Unfortunately, in my knowledge there isn’t a built-in way to completely disable Streamlit’s automatic reruns. However, we can use session state to control when the function should run and prevent multiple identical requests.
def YOURAPIREQUEST():
# Simulate a long-running process
time.sleep(10)
return "Function completed!"
# Initialize session state
if 'function_running' not in st.session_state:
st.session_state.function_running = False
if 'result' not in st.session_state:
st.session_state.result = None
# Button to trigger the function
if st.button("Run Function"):
st.session_state.function_running = True
# Display the spinner and run the function only when needed
if st.session_state.function_running:
with st.spinner("Function is running..."):
st.session_state.result = YOURAPIREQUEST()
st.session_state.function_running = False
# Display the result
if st.session_state.result:
st.write(st.session_state.result)
Yes, I am using session state. I had the same idea, but it does not work because the function is triggered again for every rerun. If you try the following code sample, you will see that the counter starts again for every random user action.
import time
import streamlit as st
def YOURAPIREQUEST():
# Simulate a long-running process
for i in range(10):
i = st.write(i)
time.sleep(1)
return "Function completed!"
# Initialize session state
if 'function_running' not in st.session_state:
st.session_state.function_running = False
if 'result' not in st.session_state:
st.session_state.result = None
# Button to trigger the function
if st.button("Run Function"):
st.session_state.function_running = True
# Random user action
if st.button("Random user action"):
st.write("Random user action")
# Display the spinner and run the function only when needed
if st.session_state.function_running:
with st.spinner("Function is running..."):
st.session_state.result = YOURAPIREQUEST()
st.session_state.function_running = False
# Display the result
if st.session_state.result:
st.write(st.session_state.result)
I cannot find a way to avoid retriggering the long function but still register its output, something like:
if not st.session_state.function_running:
st.session_state.result = YOURAPIREQUEST()
else:
# wait for the original request
If you do that, you are right you will not retrigger YOURAPIREQUEST at a random user action, but the spinner disappears and the function does not continue (at least in the discussed example case)
No, pressing the second button while the spinner is spinning instead of after
I see that was not clear from my initial post. Edited it.
The idea is:
The user sends a request to openai (long natural language task, like report generation based on a dataframe). The request takes a couple minutes.
While waiting for the response, the user either
cannot press anything in the UI to not mess with this request,
the user can take actions in the UI while awaiting the response without retriggering the request (what we have been discussing)
or the user can explore other elements of the UI (expanders, data editors), but none of their actions trigger an app rerun until the response is retrieved
So, it would be nice if st.spinner has an option disable_rerun!
I understand it a bit better !
The best i can do if it’s nested in a button it freeze until it’s finish:
if st.button('Run Function'):
if st.session_state.result is not None:
with st.spinner("Function is running..."):
st.session_state.result = YOURAPIREQUEST()
st.success
Will never enter the function with the way you initialize the session state ofcourse. Even if it did, I don’t see how it would work as st.session_state.result is only assigned when YOURAPIREQUEST() has finished.