4

I got many warnings in console when I used concurrent.futures in my streamlit app.

Some of warnings :

2020-10-28 15:43:59.338 Thread 'ThreadPoolExecutor-1_11': missing ReportContext
2020-10-28 15:43:59.338 Thread 'ThreadPoolExecutor-1_8': missing ReportContext
2020-10-28 15:43:59.339 Thread 'ThreadPoolExecutor-1_9': missing ReportContext
2020-10-28 15:43:59.339 Thread 'ThreadPoolExecutor-1_6': missing ReportContext
2020-10-28 15:43:59.339 Thread 'ThreadPoolExecutor-1_7': missing ReportContext
2020-10-28 15:43:59.340 Thread 'ThreadPoolExecutor-1_10': missing ReportContext
2020-10-28 15:43:59.340 Thread 'ThreadPoolExecutor-1_11': missing ReportContext
2020-10-28 15:43:59.341 Thread 'ThreadPoolExecutor-1_8': missing ReportContext
2020-10-28 15:43:59.341 Thread 'ThreadPoolExecutor-1_9': missing ReportContext
2020-10-28 15:43:59.342 Thread 'ThreadPoolExecutor-1_10': missing ReportContext
2020-10-28 15:43:59.342 Thread 'ThreadPoolExecutor-1_11': missing ReportContext

I knew that it should be using add_report_ctx(thread) for create the thread. (reference here)

I wonder how to use in concurrent.futures?

Here is part of my code:

def thread_run(func, values):
    with ThreadPoolExecutor(max_workers=60) as executor:
        futures = [executor.submit(func, value) for value in values]
        for future in as_completed(futures):
            yield future.result()
  • I have same problem. Not sure if this is generic to concurrent.futures module or really related to Streamlit. – avibrazil Aug 31 '21 at 12:11

1 Answers1

2

You are getting this warning because you are trying to add widgets etc. to a streamlit page from another thread, and it does not know here to send them. It is likely best not to do this, since the function will run asynchronously and you may not get your widgets in the desired order etc. A better solution would be to do any computation in the function, return the results and add the widgets etc. in the main streamlit thread.

However, if you do wish to do this, you can add the report context to the current thread in the function that will be run

def func(value, ctx):
    streamlit.report_thread.add_report_ctx(threading.currentThread(), ctx)
    # rest of func

and get the context from your thread_run function (assuming this is running on your main streamlit thread):

def thread_run(func, values):
    with ThreadPoolExecutor(max_workers=60) as executor:
        ctx = streamlit.report_thread.get_report_ctx()
        futures = [executor.submit(func, value, ctx) for value in values]
        for future in as_completed(futures):
            yield future.result()

Otherwise, collect them from wherever and just pass them through the thread_run function:

def thread_run(func, values, ctxs):
    with ThreadPoolExecutor(max_workers=60) as executor:
        futures = [executor.submit(func, value, ctx) for value, ctx in zip(values, ctxs)]
        for future in as_completed(futures):
            yield future.result()
Pete
  • 156
  • 6
  • So where this add_report_ctx() came from? Is this a Streamlit function? For clarity please edit to add complete function name. – avibrazil Nov 13 '21 at 22:22
  • thanks for pointing this out @avibrazil, please see edited answer – Pete Nov 15 '21 at 09:21