How to stop spinner when stop clicked?

When running long jobs i show spinner circle. But if i click stop while processing - spinner continue rolling.
Is there a proper way to stop spinner?

Sample code to try:

import time
import streamlit as st

button = st.button('start')
st.session_state['wait'] = True
if button:
    with st.spinner():
        while st.session_state:  # try to use this to catch stop click, in general here could be some long running task which looking for st.session_state is empty to terminate execution 
            print(st.session_state)
            time.sleep(3)

st.write('done')  # in this sample this code never executed

The while loop never ends because st.session_state never becomes falsy.

If replace
while st.session_state:
to
while True:

Logs look like this:

{'wait': True}
{'wait': True}
{'wait': True}
{'wait': True}
{}                        <--- press stop - output not stopped, and server can't be stopped with ctrl+c. In case of st.session_state - output stops here
{}
{}

That’s confusing. I am not really clear about what exactly the stop button does. Creating your own stop button may get you closer to what you need.

import time
import streamlit as st

button = st.button('start')
if button:
    stop_button = st.button("stop")
    with st.spinner():
        while True:
            st.write("running")
            time.sleep(3)

st.write('done')

When you click the new stop button streamlit reruns the script from the start, effectively exiting the while loop.

Notice that clicking start will also rerun the script but it will enter the while loop again.

@anant_raj One option is to make the button inside of the while loop, and just break if the button is pressed.

import time

import streamlit as st

button = st.button("start")
placeholder = st.empty()

if button:
    with st.spinner():
        counter = 0
        while True:
            print("Waiting...")
            if placeholder.button("Stop", key=counter): # otherwise streamlit complains that you're creating two of the same widget
                break
            time.sleep(3)
            counter += 1

st.write("done")  # in this sample this code never executed
3 Likes

As a workaround will do, thanks