St.session_state Not Reflecting Across Streamlit App

I’m encountering an issue with st.session_state.running not reflecting correctly across my Streamlit app.

I have two main buttons, “Predict” and “Generate,” that trigger different processes. The goal is to disable all interactive elements while an action is in progress using st.session_state.running as a flag.

  • When I click “Generate,” both “Predict” and “Generate” buttons are deactivated as expected.
  • However, when I click “Predict,” only the “Predict” button is deactivated, while “Generate” remains active. Additionally, st.write(st.session_state.running) at the end of the script shows False, suggesting that the rerun only executes the code above it.
import streamlit as st
import time

if 'predict_button' in st.session_state and st.session_state.predict_button == True:
    st.session_state.running = True
elif 'generate_button' in st.session_state and st.session_state.generate_button == True:
    st.session_state.running = True
else:
    st.session_state.running = False

st.write(st.session_state.running)

# Trigger fitting process
if st.button('Predict', disabled=st.session_state.running, key='predict_button'):
    
    # Fit the model and make predictions
    # Model fitting code here...
    status = st.progress(0)
    for t in range(10):
        time.sleep(.2)
        status.progress(10*t+10)
    st.session_state.output_p = 'Your Output Here'
    st.rerun()

st.write("#####")
st.write("Hello World!")

if st.button('Generate', disabled=st.session_state.running, key='generate_button'):
    st.write("Hello World!")
    status = st.progress(0)
    for t in range(10):
        time.sleep(.2)
        status.progress(10*t+10)
    st.session_state.output_g = 'Your Output Here'
    st.rerun()

if 'output_p' in st.session_state:
        st.write(st.session_state.output_p)
if 'output_g' in st.session_state:
        st.write(st.session_state.output_g)

st.write(st.session_state.running)

Any advice on ensuring consistent deactivation and proper state reflection across the app would be appreciated!

Thanks!

Hi @LiseK,

The thing to always remember is that a streamlit app just runs like a script from top to bottom.

So, in your example, if you hit the predict button, then it runs the code inside the first if, then reruns the whole script when it gets to st.rerun. So it never actually gets to running the generate button, so it doesn’t evaluate whether or not it should be disabled until the script is rerun by the st.rerun. And at that point, the st.session_state.running value has been set to False

One way to accomplish what you’re looking for is to create both buttons first, and then later use their outputs to run something. That way, both buttons will be rendered, and appropriately disabled if they should be, before any other code gets run.

import streamlit as st
import time

if "running" not in st.session_state:
    st.session_state.running = False


def is_running():
    st.session_state.running = True


# Trigger fitting process
predict_pressed = st.button(
    "Predict",
    disabled=st.session_state.running,
    key="predict_button",
    on_click=is_running,
)

st.write("#####")
st.write("Hello World!")

generate_pressed = st.button(
    "Generate",
    disabled=st.session_state.running,
    key="generate_button",
    on_click=is_running,
)

if predict_pressed:
    # Fit the model and make predictions
    # Model fitting code here...
    status = st.progress(0)
    for t in range(10):
        time.sleep(0.2)
        status.progress(10 * t + 10)
    st.session_state.output_p = "Your Output Here"
    st.session_state.running = False
    st.rerun()

if generate_pressed:
    st.write("Hello World!")
    status = st.progress(0)
    for t in range(10):
        time.sleep(0.2)
        status.progress(10 * t + 10)
    st.session_state.output_g = "Your Output Here"
    st.session_state.running = False
    st.rerun()


if "output_p" in st.session_state:
    st.write("Output_p:")
    st.write(st.session_state.output_p)
if "output_g" in st.session_state:
    st.write("Output_g:")
    st.write(st.session_state.output_g)

st.write(st.session_state.running)

You are amazing, Thank you!

1 Like

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.