I am running my app locally for now, and seem to be having trouble with the checkbox staying checked.
Working version:
It works well when I use a range of numbers for keys but since I am looping multiple times in my original code, I eventually will hit the duplicate widget ID error.
widget_id = (i for i in range(2))
for i in range(2):
st.checkbox(f"Download latest {i}", key = next(widget_id))
Non working version:
To avoid that, I used a random number generator for the key. Now, the checkbox does not stay checked at all, throwing off the flow of my code.
def infinite_random_number(start:int=0, end:int=10):
while True:
yield random.randint(0,10)
widget_id = infinite_random_number()
for i in range(2):
st.checkbox(f"Download latest {i}", key = next(widget_id))
All this was to avoid duplicate widget id error. I tried generating numbers in a large range but I ran out of unique keys looks like after some runs.
I searched through forums, etc. for solutions but seemed to settle on this which is causing this behavior.
Alternatively, if there is a good solution out there for doing multiple runs and not get duplicate widget id, I am open to that too.
Thanks for the response.
This is my original code snippet.
I am trying to reproduce the problem now with this and am not able to (lot of experiments in the middle might have reset widget id values) but when I keep killing and restarting app multiple times, at some point, I hit the error. I cannot keep streamlit running since it is a shared test machine and I cannot block it for only this. I am thinking, that every restart the key gets assigned a new key and at some point, it hits duplicates. The other part was it seemed to be stuck at the first index for some reason.
#init to avoid out of index range error
input_latest_firmware = [i for i in range(5)]
input_customized_firmware = [i for i in range(5)]
version_filter = [i for i in range(5)]
input_customized_firmware_path = [i for i in range(5)]
firmware_types = ['fw_type1','fw_type2','fw_type3','fw_type4']
widget_id = (i for i in range(10_000))
#customized firmware will provide options to filter by version or a custom path to copy from
for i,type in enumerate(firmware_types, start =0):
input_latest_firmware[i] = st.checkbox(f"Download latest {type} firmware",key = next(widget_id))
input_customized_firmware[i] = st.checkbox(f"Customized {type} firmware", key = next(widget_id))
if input_customized_firmware[i]:
version_filter[i] = st.text_input(f"Requested {type} Version, use format x.x.x.xx: ")
st.write(" OR ")
input_customized_firmware_path[i] = st.text_input(f"Enter local path of {type} firmware hex file: ")
download_ready = st.button("Download", key = next(widget_id))
The other thing I have been thinking of to get around with streamlit to continue to run is having a docker image with streamlit running all the time. The image is launched by user when required. I am relatively new to docker too so not sure if this is a fanciful thinking. I know I am going off on a tangent, but the duplicate widget id issue has been real and ate away a lot of my time, than me spending time on actually working on my app.
And you select “Customized fw_type1 firmware” twice, then duplicated text input widgets will be created. The way you generate the keys is irrelevant, since you are not assigning keys to these widgets.
I see. I do allow the users to pick between latest and customized between runs.
Run1:
fw_type1 could be with latest firmware checkbox and then press download.
Run2:
fw_type1 could be customized firmware checkbox and press download.
But they do have different keys depending on which one, latest or customized, because of the iterator.
Am I understanding this correctly.
I don’t understand what you mean here. I don’t think you can create duplicated widgets this way. I already told you how to trigger the error and why it happens.