Concurrency with streamlit

Hey

I want to run a code concurrently with streamlit, i’m trying to use threads, and I’m getting this error:
2022-08-19 08:09:33.852 Thread 'Thread-11': missing ScriptRunContext

Code:

from pathlib import Path
from threading import Thread


def target():
    st.text(c)

if __name__ == '__main__':
    if not st.session_state.get("thread"):
        st.session_state["thread"] = True
        t = Thread(target=target)
        t.start()

Can you please help ? What is the best solution to use concurrency with streamlit?

Hi @royassis, welcome to the Streamlit community! :wave: :partying_face:

Here’s a GitHub issue where the solution is discussed in the comments:

1 Like

Thanks @snehankekre.

I added an example of how to import add_script_run_ctx in streamlit==1.12.0

@snehankekre @royassis
I was unable to make this code below work. Any ideas how to fix it?

The loop in the thread target works because I see the console print outs, but only the first iteration is printed in Streamlit.

import time
import streamlit as st
import threading
try:
    # Streamlit >= 1.12.0
    from streamlit.runtime.scriptrunner import add_script_run_ctx
    from streamlit.runtime.scriptrunner.script_run_context import get_script_run_ctx
except:
    # Streamlit <= 1.11.0
    from streamlit.scriptrunner import add_script_run_ctx
    from streamlit.scriptrunner.script_run_context import get_script_run_ctx

def st_write_log(message):
    st.write(message)
    print(message)

def thread_target(iterations, seconds):
    for i in range(iterations):
        st_write_log(f"thread_target ({i})")
        time.sleep(seconds)
    st_write_log('=== END (Refresh or CTRL-C) ===')

t = threading.Thread(target=thread_target, args=(5,1))
ctx = get_script_run_ctx()
print('=== CTX ===\n', ctx)
add_script_run_ctx(t)
t.start()

I haven’t been able to install Streamlit 1.12.0 successfully yet, so haven’t tried it in that version yet.

Thanks,
Arvindra

Hi @snehankekre - do you know how to get this script :point_up_2:t5: to work, i.e. report message in Streamlit?

Any luck with this?
I’ve encountered the same need and the same error. I’m using streamlit 1.23 but still no luck

Hi @asehmi,

Did you get a solution to use the st write function in threads? I have the same problem.

Here’s what I did to get threading working correctly – you were right with the context stuff, it just looks like you didn’t start it low enough in the call stack:

import queue
import threading
import streamlit as st
from streamlit.runtime.scriptrunner import add_script_run_ctx
from streamlit.runtime.scriptrunner.script_run_context import get_script_run_ctx

def thread_task(ctx, in_q, out_q):
    '''
    this runs in a thread, needs a context
    '''
    add_script_run_ctx(ctx) # register context on thread func
    while not in_q.empty():
        job = in_q.get()
        result = do_stuff(job)
        out_q.put(result)
        in_q.task_done()

def run_in_parallel(iterable, func, n_threads=10):
    '''
    not running in a thread; running in main context, spawns threads.
    '''
    ctx = get_script_run_ctx() # create a context
    job_q = queue.Queue()
    for thing in iterable:
        job_q.put(thing)
    out_q = queue.Queue()

    for _ in range(n_threads):
        # pass context to thread
        threading.Thread(target=thread_func, args=(ctx, job_q, out_q), daemon=True).start()

    in_q.join()

...