Refresh, skipping rest of script executions, and retries

I’m trying to poll results at the server side, if there are no results at the moment, I use time.sleep(2), and then try again. I’m showing st.write(“Fetching…”) in st.empty(), and replacing it with the results once I have something. This actually works nice. The GUI is responsive and I get the results on the browser as soon as they reach the relevant database.
My issue is, if I decide not to wait for the results, but rather change the parameters that are already shown and enabled on the screen, I still need to wait for having results for the previous parameters, it will not break out of my polling loop otherwise.

So, I’m asking if there is already a recipe how to handle such use cases. Something I can do at the script level? Something I need to do in Javascript? Is there st.timer() or something similar?

A lot of thanks in advance.

Apparently I’m not the first to try or ask about it.
See for example a solution: okld’s gists (github.com). If you try above, use the latest packages (replace some old ones):


from streamlit.report_thread import get_report_ctx
from streamlit.server.server import Server

If I understand correct what is happening there, a thread awakes, every so and so, and request_rerun from the session. This solves my problem as the script is done and if you change the parameters at the browser, this change triggers a rerun (as expected), and the thread, a single one handled by careful accounting in the session, can check once it is awaken, if it needs to do anything (and request_rerun), or not.

I saw also mentions of st.stop() and st.rerun(), yet I do not know if something has happened with those.

Hello @Oren_Zeev_Ben_Mordeh

I don’t know which version of Streamlit you have, but in the latest ones, you have access to st.stop() and st.experimental_rerun(). That (outdated) st_demo_rerun gist was made before st.experimental_rerun() was available.

1 Like

I’ve tried the code above (old solution), with the thread, left it as is, just changed session.request_rerun to st.experimental_rerun. I get an exception. This does not seem to be the intended use, or may not be the solution for the challenge I’ve described above. I’ll continue with the old implementation that seems still to work, till learning something new. Will be very happy for additional brainstorming about this scenario.

For additional brainstomring, could you share some code sample, and more details on that exception you had?

Exception in thread Thread-17:
Traceback (most recent call last):
File “C:\Users\zbenm\miniconda3\lib\threading.py”, line 932, in _bootstrap_inner
self.run()
File “C:\Users\zbenm\miniconda3\lib\threading.py”, line 870, in run
self._target(*self._args, **self._kwargs)
File “C:\Users\zbenm\projects\SpaceGuests\demo1\st_tmp.py”, line 31, in rerun_session
st.experimental_rerun()
File "c:\users\zbenm\projects\spaceguests\env\lib\site-packages\streamlit_init
.py", line 562, in experimental_rerun
raise _RerunException(_RerunData(None))
streamlit.script_runner.RerunException: <streamlit.script_request_queue.RerunData object at 0x000001B241C11100>

import random

import streamlit as st

from streamlit.report_thread import get_report_ctx

from streamlit.server.server import Server

from threading import Thread

from time import sleep

def main():

    st.line_chart(random.sample(range(100), 20))

    

    st.write(st.text_input("You can still interact with widgets."))

    st.write(st.slider("You can even slide normally.", 0, 10))

    rerun(2)

def _get_session():

    session_id = get_report_ctx().session_id

    session_info = Server.get_current()._get_session_info(session_id)

    if session_info is None:

        raise RuntimeError("Couldn't get your Streamlit Session object.")

    

    return session_info.session

def _rerun_session(session, delay):

    sleep(delay)

    # session.request_rerun()

    st.experimental_rerun()

def rerun(delay=0):

    session = _get_session()

    if delay <= 0:

        session.request_rerun()

    elif hasattr(session, "_rerun_thread") and session._rerun_thread.is_alive():

        return

    

    session._rerun_thread = Thread(target=_rerun_session, args=(session, delay))

    session._rerun_thread.start()

if __name__ == "__main__":

    main()