-1

Hide button while model is running in Streamlit.

Hi,

I am developing an application, which infer an stable diffusion model when RUN button is pressed. How can i disable/hide this RUN button while model is running, and enable/show it again when done.

Thanks.

2 Answers2

1

One thing to keep in mind is that if you have any other buttons/widgets on the page then a user interacting with those could also interrupt your long process. So if you do have anything else on the page, you may want to think about locking those other ones as well.

Here's an example to show what I mean. Try this out and see that you can click buttons before the page finishes loading. You can even click "shadow buttons" from the previous page load.

import streamlit as st
import time

for i in range(10):
    st.button(f'Button {i}')
    time.sleep(.5)

Three variations

Lock Run button at the start of processing and until results are cleared

I put an extra "Do Nothing" button at the bottom. You will see that it disappears during processing and comes back. There is nuance to when Streamlit will hold on to or discard "shadow elements" when reloading the page. And the nuance may vary between versions of Streamlit since it factors in backend optimization of reruns. I tested these in Streamlit 1.22 for reference. See the third example for forcibly removing a "shadow element" using st.empty().

import streamlit as st
import time

def expensive_process():
    with st.spinner('Processing...'):
        time.sleep(3)
    return 42

if 'run' not in st.session_state:
    st.session_state.run = False
    st.session_state.result = None

def run():
    st.session_state.run = True

def clear():
    st.session_state.result = None

lock = st.session_state.run or st.session_state.result is not None
st.button('Run', on_click=run, disabled=lock)

if st.session_state.run:
    st.session_state.result = expensive_process()
    st.session_state.run = False

if st.session_state.result is not None:
    st.write(st.session_state.result)
    st.button('Clear', on_click=clear)

st.button('Do Nothing')

Lock Run button at the start of processing and reactivate as soon as finished

Streamlit is discarding the "Do Nothing" button by itself in this example as well.

import streamlit as st
import time

def expensive_process():
    with st.spinner('Processing...'):
        time.sleep(3)
    return 42

if 'run' not in st.session_state:
    st.session_state.run = False
    st.session_state.result = None

def run():
    st.session_state.run = True

def clear():
    st.session_state.result = None

st.button('Run', on_click=run, disabled=st.session_state.run)
result_area = st.empty()

if st.session_state.run:
    result_area.empty()
    st.session_state.result = expensive_process()
    st.session_state.run = False
    st.experimental_rerun()

if st.session_state.result is not None:
    result_container = result_area.container()
    result_container.write(st.session_state.result)
    result_container.button('Clear', on_click=clear)

st.button('Do Nothing')

Hide the Run button at the start of processing and show again at the end of processing

This uses st.empty to forcibly clear the screen

import streamlit as st
import time

def expensive_process():
    with st.spinner('Processing...'):
        time.sleep(5)
    return 42

if 'run' not in st.session_state:
    st.session_state.run = False
    st.session_state.result = None

def run():
    st.session_state.run = True

def clear():
    st.session_state.result = None

main = st.empty()
body = main.container()

if not st.session_state.run:
    body.button('Run', on_click=run)
else:
    main.empty()
    time.sleep(.2) # Bug workaround to enforce main.empty()
    body = main.container()

if st.session_state.run:
    st.session_state.result = expensive_process()
    st.session_state.run = False
    st.experimental_rerun()

if st.session_state.result is not None:
    body.write(st.session_state.result)
    body.button('Clear', on_click=clear)

body.button('Do Nothing')
MathCatsAnd
  • 601
  • 2
  • 8
0

You can use st.empty to clear the button while the model is running, and then add a new button when it's done running.

import streamlit as st
import time

with st.empty():
    for seconds in range(60):
        st.write(f"⏳ {seconds} seconds have passed")
        time.sleep(1)
    st.write("✔️ 1 minute over!")
Caroline Frasca
  • 511
  • 2
  • 10