Why app runs from first line for every action (button,selectbox,checkbox)?

when i use checkbox/selectbox/radio features to filter data to be shown as plots on tool, it reruns entire app.py script and starting from loading data again. Have I overlooked or missed something to include in my code to avoid this kind of problems.

My code is given here:

df_uploaded = st.sidebar.file_uploader(‘Choose txt file:’,type = [‘txt’,‘csv’])

@st.cache(hash_funcs={StringIO: StringIO.getvalue})
def load_data(file_uploaded):
    return (pd.read_table(file_uploaded,header=None,encoding=‘utf-8’))
if df_uploaded:
    temp = load_data(df_uploaded)
select_cols = st.selectbox('Choose column for analysis', list(temp.columns))
if select_cols:
    ** code to plot the variable distribution/scatter plot

Hello @santosh_boina,

Actually, the way Streamlit works (as per the doc if you want to read more about it) is :

any time something must be updated on the screen, Streamlit just reruns your entire Python script from top to bottom.

so each time you interact with a widget, all of the script reruns with the updated value for your selectbox. But it will not rerun the functions where you put a cache annotation and if the value of the passed argument did not change (like your uploaded file, which stays the same each time you choose another column because you did not select a new file with a different content).

You can try to print some text inside the load_data function to see on your UI if you are loading the data again (check this excellent example from the docs :slight_smile:) like so :

from io import StringIO
import pandas as pd
import streamlit as st

df_uploaded = st.sidebar.file_uploader('Choose txt file:', type = ['txt', 'csv'])

@st.cache(hash_funcs={StringIO: StringIO.getvalue}, suppress_st_warning=True)
def load_data(file_uploaded):
    st.write("I ran !") # <--- this should be printed on your app each time this function is run
    return pd.read_csv(file_uploaded, sep=',', encoding='utf-8')

if df_uploaded:
    temp = load_data(df_uploaded)

    select_cols = st.selectbox('Choose column for analysis', list(temp.columns))

    if select_cols:
        st.write(select_cols)

by interacting with your app, you should notice the first time you upload data the sentence I ran ! appears on your app, but then each time you interact with the selectbox widget, your script is rerun entirely as you noticed, except for the cached function and you shouldn’t see the I ran ! part.

Moreover, you can then try to clear the cache on the top right of your app, in the hamburger menu there’s a Clear cache, if you clear the cache and reselect a column you should see the I ran ! sentence.

streamlit


So yes, Streamlit reruns all your script each time there is an interaction, except for any function you put a cache annotation on ! You can review this here.

1 Like

Hello. Looking at your answer, is there any way to store a selectbox variable in cache when the source code is updated?
I have a csv source which gets updated every 5 min, every time a new file is generated, the code is rerun and the current session is lost (and all the filters due to change in source). Moreover, I tried to overcome the situation using a button:

date = st.sidebar.date_input("Select a date",value=now,max_value=now,min_value=pd.to_datetime(os.listdir(path)[1][-19:-9]))

def inner_load():
    update_timestamp = time.ctime(os.path.getmtime(path))
    return update(update_timestamp)

@st.cache(ttl=60)
def update(timestamp):
    new_table_list = []
    for filename in os.listdir(path):
        if date.strftime("%m-%d-%Y") in filename:
            new_table_list.append(filename[-19:-4])
    return new_table_list
    
session_state = SessionState.get(a='',b=2)

if st.button("Update"):
    session_state.a = inner_load()
1 Like

Hi @betinhosaad did you find a solution for this?