Asynchronous code fails to use session state on Streamlit Cloud while it works locally

The error appears while running an asynchronous chronometer controlled by a Streamlit interface. The session state variables are failed to be used on the deployed version on Streamlit Cloud, while the same code works perfectly fine locally.

Reproducible Code Example

The repository with the full reproducible code and the used requirements.txt file can be found here.

import asyncio
import time

import streamlit as st


async def run_chronometer(container):
    run_time = 0.0
    while st.session_state["chrono_running"]:
        st.session_state["chrono_stop_ts"] = time.time()
        run_time = (
            st.session_state["chrono_stop_ts"] - st.session_state["chrono_start_ts"]
        )
        container.subheader(f"{run_time:.2f}")
        await asyncio.sleep(0.01)


def init_chrono():
    st.session_state["chrono_running"] = False
    st.session_state["chrono_start_ts"] = None
    st.session_state["chrono_stop_ts"] = None


if "chrono_running" not in st.session_state:
    init_chrono()

st.header("Chronometer")
col1_run, col2_run = st.columns(2)
container = st.empty()
col1_save, col2_save = st.columns(2)

# buttons to run chronometer
with col1_run:
    if st.button("Start", use_container_width=True):
        st.session_state["chrono_start_ts"] = time.time()
        st.session_state["chrono_running"] = True
        st.session_state["chrono_stop_ts"] = None

with col2_run:
    if st.button("Stop", use_container_width=True):
        st.session_state["chrono_running"] = False

# fill container when chrono is not running
if not st.session_state["chrono_running"]:
    if not st.session_state["chrono_stop_ts"]:
        container.subheader(f"{0.0:.2f}")
    else:
        run_time = round(
            st.session_state.chrono_stop_ts - st.session_state.chrono_start_ts, 2
        )
        container.subheader(f"{run_time:.2f}")

# buttons to save chronometer result
with col1_save:
    if st.button(
        "Save",
        disabled=(not st.session_state["chrono_stop_ts"]),
        use_container_width=True,
    ):
        st.write("Saved time:", run_time)

with col2_save:
    if st.button(
        "Delete",
        disabled=(not st.session_state["chrono_stop_ts"]),
        use_container_width=True,
    ):
        init_chrono()
        st.experimental_rerun()

# run chronometer asynchronously
asyncio.run(run_chronometer(container))

Steps To Reproduce

Go to the deployed version.

Then follow these steps:

  • Click on “Start” button
  • Click on “Stop” button
  • Click on “Save” or “Delete” buttons
  • Click on “Start” button again
  • Click on “Stop” button again

The following error message will pop up:

Traceback (most recent call last):

  File "/home/appuser/venv/lib/python3.10/site-packages/streamlit/runtime/scriptrunner/script_runner.py", line 565, in _run_script

    exec(code, module.__dict__)

  File "/app/streamlit-chronometer/chronometer.py", line 78, in <module>

    asyncio.run(run_chronometer(container))

  File "/usr/local/lib/python3.10/asyncio/runners.py", line 44, in run

    return loop.run_until_complete(main)

  File "/usr/local/lib/python3.10/asyncio/base_events.py", line 649, in run_until_complete

    return future.result()

  File "/app/streamlit-chronometer/chronometer.py", line 14, in run_chronometer

    while st.session_state["chrono_running"] and run_time < MAX_TIME - TIMESTEP_REAL:

  File "/home/appuser/venv/lib/python3.10/site-packages/streamlit/runtime/state/session_state_proxy.py", line 90, in __getitem__

    return get_session_state()[key]

  File "/home/appuser/venv/lib/python3.10/site-packages/streamlit/runtime/state/safe_session_state.py", line 104, in __getitem__

    raise KeyError(key)
KeyError: 'chrono_running'

And the stop time will always fail to be captured from now on.

Debug info

  • Streamlit version: 1.19
  • Python version: 3.10
  • Operating System: Windows

Additional Comments

If you try to use streamlit==1.20+, you would obtain the same error locally as well. I found out this is due to the fastReruns default value which has become true in these releases. If you overwrite the value to false within .streamlit/config.toml file, you would solve the problem locally but it will persist on the deployed version. Using streamlit==1.19 overcomes this problem.

I see you created a bug report on GitHub. Thank you! I will link it here for anyone else stumbling across this thread so that comments can be directed there to help the devs track the size of the impact.

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