Displaying a changing variable

Say you have a variable x that changes value in a while loop, and you want to display this variable. I tried st.write(x) but it just writes it line after line. The variable is always decreasing in value so I guess I can use a progress bar to display it, but I wonder if there are other ways to display it without it producing a new line in each iteration?
Thanks

Check out st.empty โ€“ it creates a placeholder you can update.

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!")

Thanks. But when I used st.empty() in my cached function, the function seems to lose the caching ability as it reruns each time.

Post up a minimal example of what you are doing / trying to accomplish

import streamlit as st

@st.cache_data(show_spinner=False)
def append_list(num_iterations):
    with st.spinner('This might take awhile...'):
        mylist = []
        with st.empty():
            for i in range(num_iterations):
                st.write(f"Iteration number is {i}")
                mylist.append(i)
    return mylist

output = append_list(10000)
selection = st.selectbox('Make a selection', ['Good','Bad'])
if selection == 'Good':
    st.write('You selected Good')
else:
    st.write('You selected Bad')

In the above code, I have the iteration number displayed in place using st.empty(), and the function is cached. However, if the user toggles the selection box at the bottom, the iteration number go from a low number to max, and itโ€™s slow, even though the function is cached and it only outputs an appended list.

Iโ€™ve tried your example and honestly to me it seems like it is working as expected. Itโ€™s hard to notice the speed difference between the first and subsequent runs because the function isnโ€™t doing any work right now and is so blazing fast anyway โ€“ the screen updates take most of the time.

Here is a slightly reworked version of your code that makes it more obvious the cache is working:

import time

import streamlit as st


@st.cache_data(show_spinner=False)
def append_list(num_iterations):
    with st.spinner("This might take awhile..."):
        mylist = []
        count = 0
        with st.empty():
            for _ in range(num_iterations):
                for _ in range(10000):
                    count += 1
                    st.write(f"Iteration number is {count}")
                    mylist.append(count)
                time.sleep(1)

    return mylist


output = append_list(5)
selection = st.selectbox("Make a selection", ["Good", "Bad"])
if selection == "Good":
    st.write("You selected Good")
else:
    st.write("You selected Bad")

The first time you re-run it, youโ€™ll notice the 1 second sleeps between each of the blocks of 10,000. Subsequent re-runs will not have this delay and will iterate up to 50,000 as fast as Streamlit can process the cached messages.

I was actually surprised this worked this way, I didnโ€™t realize the messages from โ€œst.whateverโ€ calls got replayed from within a function decorated with cache_data. I looked into the code a bit and found that this is intended and expected โ€“ cool!

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