Issue with threading: text not displayed

Hello everyone,

I’m pretty new to Streamlit, still trying to figure out how it all works.

What I’m currently trying to do is set up a logging receiver that just displays a text element on the Streamlit dashboard from a subthread.

I’m using add_report_ctx to add the ReportContext to the thread before starting it. The thread runs and receives log messages via ZeroMQ. It calls st.text to create text elements. The thing is, they are never displayed very rarely and infrequently. I don’t see a pattern under which the dashboard refreshes. It seems like some refresh mechanism isn’t being triggered on every call to text or other st-members.

What might be the reason here? What am I missing?

Thank you

edit 1: added some details regarding the refreshing behavior

Update I’ve sort of solved this issue by switching from threading to asyncio. No issues there. I just can’t use the event loop directly. AsyncIO always claims that there’s no loop running even though my tasks work like a charm. Weird…

1 Like

Glad you figured out a work-around @HWiese1980, and welcome to the Streamlit community!

1 Like

Thank you, Randy. That asyncio issue remains, though and makes it difficult to run multiple “parallel” tasks. For the time being I have one task that has an if block splitting between the different ZMQ topics. I’d like to have a distinct one for each topic. The asyncio issue with the allegedly not running event loop prevents me from it. But that’s a different story, not in the scope of this topic! Just felt like mentioning it.

I’m wondering if it’s an issue where Streamlit itself is running multiple threads, so maybe the context gets lost somewhere. @thiago, do you know anything about this?

Hi @HWiese1980 :wave:

I can’t repro the issue when I try the toy example below. Is this more or less what you’re doing on your end?

import streamlit as st
from streamlit import ReportThread
from threading import Thread
import time

SLEEP_TIME = 0.01

ctx = ReportThread.get_report_ctx()

def print_numbers(thread_id):
    ReportThread.add_report_ctx(None, ctx)
    output = st.text("")
    for n in range(1000):
        output.text("Thread %s: %s" % (thread_id, n))
        time.sleep(SLEEP_TIME)

thread = Thread(target=print_numbers, args=(2,))
thread.start()

print_numbers(1)

Hi! @thiago

I adjusted your example to a problem that I’m having in my app.

import streamlit as st
import streamlit.report_thread as ReportThread
from threading import Thread
import time

SLEEP_TIME = 0.01

ctx = ReportThread.get_report_ctx()


def print_numbers(thread_id):
    ReportThread.add_report_ctx(None, ctx)
    output = st.text("")
    for n in range(1000):
        output.text("Thread %s: %s" % (thread_id, n))
        time.sleep(SLEEP_TIME)


if st.button('Push'):
    thread = Thread(target=print_numbers, args=(2, ))
    thread.start()

st.subheader('Something')
st.text_input('Write something')
st.selectbox('Select something', range(10))

I nede to run the Thread when the button is pushed, but I would love to print the progress as well, this particular part output.text("Thread %s: %s" % (thread_id, n)). However, just like in this example the text is not updating with each iteration.

If there is something that I’m doing wrong or a solution I will really appreciate it.

Edit: I just notice that the text updates if a do something that re-runs the script, but then it stays in that value until I do something that re-runs the script again. In other words, the loop runs in the background as I want, but it does not print the progress as I wish.