I am trying to create a simple app using Streamlit which essentially boils down to three steps:
A user specifies what data to load.
The data is loaded and cached.
Some statistics for this data is displayed.
A simple toy example:
x1 = st.sidebar.text_input('Input x1')
x2 = st.sidebar.text_input('Input x2')
if st.button('Load data'):
data = load_data(x1, x2)
if st.checkbox('Show mean'):
st.text(data.mean())
if st.checkbox('Show median'):
st.text(data.median())
The load_data function is decorated with st.cache.
The problem is that when I switch on a checkbox, I get: NameError: name 'data' is not defined.
I do realise that it happens because Streamlit reads the whole file from top to bottom each time I change something (e.g. I switch on/off a checkbox) and when I use one of the checkboxes, data is lost. However, there must be a way to get this data somehow since itās been cached.
Is there some way how I can get a reference to the cached data apart from duplicating data = load_data(x1, x2) within each st.checkbox block?
Note, I am new to Streamlit and might be missing some basic functionality.
This looks like a case where you just need to insert a line near the top of your script that says data = None so that the variableās scope is global. Right now your data declarations are all structured underneath if statements.
Iām only basing my response on the sample code youāve provided. So if this doesnāt solve your problem, let me see the rest of your code and Iāll try to help some more.
Just get rid of the if statement to load data. Make sure that the default values for x1 and x2 (currently 1 and 10) are sane, and load the data every time the script runs. Otherwise youāre going to have all kinds of problems with the button activating and deactivating.
I realise that this is a toy example. If your real example has intermediate states where the data is invalid while the user is entering one of the boxes, but not the other, you probably will need to detect this somehow, and only run the rest of the script when the entries are sane.
I realise that this is a toy example. If your real example has intermediate states where the data is invalid while the user is entering one of the boxes, but not the other, you probably will need to detect this somehow, and only run the rest of the script when the entries are sane.
This is exactly why I wrapped the load_data up with a button - I was trying to prevent the app from executing further until a user is happy with the input parameters. So far the best what Iāve got is:
import streamlit as st
import numpy as np
import time
@st.cache
def load_data(x1, x2):
time.sleep(5)
return np.arange(x1, x2)
x1 = st.sidebar.number_input('Input x1', value=1.)
x2 = st.sidebar.number_input('Input x2', value=10.)
if st.checkbox('I am done with input parameters'):
data = load_data(x1, x2)
st.text(data.mean())
# other widgets, etc.
What I would really love to have in Streamlit is a native input form with multiple variables to enter and with a Submit/Ready button. The app would only be rerun after the user clicks on that button.
You can do that. Itās just that the button will turn off again the next time any alteration is made to the form. The checkbox will stay on, but then youāre just back to the original issue of it running through every time you change the inputs.
Sounds like you might be better off with the button. If you want further checkboxes for the mean etc, probably put them before the ācalculationā button.
You can use st.empty() if you want them to appear in a different order (eg have the āproceedā button further up the page, but at a later point in the flow of the actual script to block the execution).
st.empty() is indeed interesting and gives more flexibility. However, I could not come up with anything that would solve my problem. I will keep trying.
If you are aware of any good streamlit code examples relevant to this, feel free to give a link here.
Thanks again.
Iām still not quite sure what actual problem you are trying to solve.
Using a button to trigger the calculation rather than having the calculation always run seems to solve the problem that you have actually described.
If what you want is to display a result, and then keep displaying the result but turn off the live calculations, then you have a different problem. This is about maintaining state, which is tricky but entirely possible - there are many potential threads about maintaining state between program runs.
Perhaps you could give us a more thorough description of what you would like your script to do on first and subsequent runs, and what it doesnāt currently do.
As a ludicrously simple example, look at this code:
import streamlit as st
@st.cache(allow_output_mutation=True,persist=True)
def persist_dict():
return []
dict=persist_dict()
st.write("The dict contains", dict)
new=st.text_area("Enter new stuff")
if st.button("Rerun"):
st.balloons()
dict.append(new)
st.write(new)
Note that this data will be visible to anyone using the app until you reset the cache.
In my real app, I have multiple plots and statistics to show. It is hard to know in advance which of them are interesting. E.g. I want to look at plots B and C only if plot A shows something interesting and the other way around. There are also interactions with the plots using other widgets (e.g. to change the smoothing window size).
Any time I want to interact with a plot or select more plots, I would also need to click on the āLoad dataā button to see the change (even though there will be no actual re-calculation). Seems like an unnecessary complication.
I am new to Steamlit and am probably still thinking in terms of Jupyter notebook where I have 3 cells with input parameters, a data loader, and a plotting script. I will try to come up with a better logic for my app.
Thanks.
You can just clear the dictionary - there should be a .clear() method which would achieve this. Alternatively you can clear the streamlit cache via the top right system menu, or pressing āCā with the interface loaded.
Thanks for stopping by! We use cookies to help us understand how you interact with our website.
By clicking āAccept allā, you consent to our use of cookies. For more information, please see our privacy policy.
Cookie settings
Strictly necessary cookies
These cookies are necessary for the website to function and cannot be switched off. They are usually only set in response to actions made by you which amount to a request for services, such as setting your privacy preferences, logging in or filling in forms.
Performance cookies
These cookies allow us to count visits and traffic sources so we can measure and improve the performance of our site. They help us understand how visitors move around the site and which pages are most frequently visited.
Functional cookies
These cookies are used to record your choices and settings, maintain your preferences over time and recognize you when you return to our website. These cookies help us to personalize our content for you and remember your preferences.
Targeting cookies
These cookies may be deployed to our site by our advertising partners to build a profile of your interest and provide you with content that is relevant to you, including showing you relevant ads on other websites.