Live plot from a thread

Hi @robmarkcole

To use Streamlit outside the main thread you need to grab some special objects and use them to write to the app inside the thread. This depends on some obscure Streamlit internal details, so I created a little wrapper to make your life easier: Hack to write to Streamlit app from another thread. See: https://discuss.streamlit.io/t/live-plot-from-a-thread/247 · GitHub

How to use it:

# This must be called from the main thread:
thread_safe_st = ThreadSafeSt()

def function_called_from_another_thread(arg1, arg2, st):
  st.main.markdown('arg1 is: %s' % arg1)
  st.sidebar.markdown('arg2 is: %s' % arg2)

# On another thread:
function_called_from_another_thread(10, 20, thread_safe_st)

Also I am not sure if using a while True to maintain the app is best practice?

Since you’re using mqtt, you should be able to replace the while True with just client.loop_forever(). See relevant docs here.

So I think the code would look like this in the end:
(Note: this is untested!)

import paho.mqtt.client as mqtt
import streamlit as st
import time
from thread_safe_st import ThreadSafeSt

MQTT_BROKER = 'localhost'

thread_safe_st = ThreadSafeSt()

# The callback for when the client receives a CONNACK response from the server.
def on_connect(client, userdata, flags, rc):
    # Note: st.write is not supported in thread_safe_st yet, but will be soon!
    # See https://github.com/streamlit/streamlit/pull/238
    thread_safe_st.markdown(
      f"Connected with result code {str(rc)} to MQTT broker on {MQTT_BROKER}")

def on_disconnect(client, userdata,rc=0):
    print("DisConnected result code "+str(rc))
    client.loop_stop()

# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):
    thread_safe_st.text(str(msg.payload))

client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect(MQTT_BROKER)
client.subscribe("streamlit")

client.loop_forever()
1 Like