file_uploader does not repopulate the UploadedFile stream when the app is rerun
See original GitHub issueSummary
I use st.file_uploader
to allow the user to submit their own data. Then I do an action based on this data and other user-provided parameters (coming from an st.slider
for instance). Re-running the app produces an error. This includes when the parameters are changed (for example by moving the st.slider
). After investigating, I discovered that it is because, after the first reading of the UploadedFile output by st.file_uploader
, the UploadedFile stays empty. It is not re-populated by the uploaded file in spite of the app re-running.
Steps to reproduce
- Save the following JSON as “test.json”:
{"a": 3, "b": 2}
- Save the following piece of code as “my_app.py” (or any other name):
import json
import streamlit as st
st.title("Let's add a number to the elements of a json")
uploaded_file = st.sidebar.file_uploader(
"Upload your json", type=["json"]
)
to_add = st.sidebar.slider(
"Choose a number", min_value=1, max_value=5, value=3
)
st.markdown("The result is:")
default_file = open("test.json", "r")
if uploaded_file is None:
dico = json.load(default_file)
else:
dico = json.load(uploaded_file)
st.write({k: v + to_add for k, v in dico.items()})
default_file.close()
- Run
streamlit run my_app.py
- In the app, upload test.json in the file uploader. You should see that:
- Move the slider, here is the bug, you should see that:
- At this point, re-uploading works, but the user shouldn’t have to re-upload the file after each slider change or each plain re-run. Especially since, as we see in the screenshot above, the widget still displays the informations of the uploaded file. Here is how it looks after re-uploading:
Expected behavior:
We shouldn’t ever get to the second screenshot. We should pass from the first to the third simply by moving the slider and without re-uploading the file every time.
Actual behavior:
As explained above, after the first run the stream is empty and not reset when the app is re-run. This is not specific to the JSON format, although the error message displayed above is. I have run the same test with a CSV file and pandas.read_csv
. The underlying cause is the same: an empty stream.
Note that I have also tried to make an auxiliary function that encapsulates the dico = json.load(uploaded_file)
part and which is decorated by st.cache
. It still doesn’t work.
Is this a regression?
I don’t know, it’s the first time I use st.file_uploader
.
Debug info
I have two different settings.
An AWS distant machine (I forward the port to my local machine):
- Streamlit version: 0.69.1
- Python version: 3.7.6
- Using Conda
- OS version: I don’t know
My local machine:
- Streamlit version: 0.68.0
- Python version: 3.8.5
- Not using Conda
- OS version: macOS 10.13.6
- Browser version: Firefox 81.0.1
Additional information
Side note on the documentation of st.file_uploader
: at the some point it says to use StringIO(uploaded_file.decode("utf-8"))
but this doesn’t work and raises AttributeError: 'UploadedFile' object has no attribute 'decode'
. Using StringIO(uploaded_file.read().decode("utf-8"))
does work, though.
Issue Analytics
- State:
- Created 3 years ago
- Comments:5 (1 by maintainers)
Exalate commented: FrankKr commented: Update: Actually, it appears the UploadedFile stream is available, but the cursor is at the end of the stream after the first evaluation. A work-around for me was to reset the cursor by including
uploaded_file.seek(0)
after the check if uploaded_file is None. Would very much prefer this workaround to become obsolete.in your example:
original: experiencing the same issue after upgrading streamlit from version 0.64.0 to 0.69.0
Closing this issue as a duplicate of #2235. A fix for this should be coming in the next release. Please track #2235 for updates.