Hi everyone,
I need to run a dash app in a separate thread inside a main backend application (Qt).
I need to communicate with Dash after running the dash app. Because dash callbacks must be initialized beforehand so i must use websockets to send server->client message from my main backend application.
This works well with a combination of Dash-Extensions and Quart websockets, as long as Quart runs in the main application.
See dash_extensions WebSocket example
Even with quart + dash running in the same main app
But my main backend program also requires also the websocket server to run in it’s separate thread.
Unfortunately Quart websockets cannot run in a thread (never easy…). So I’m trying to do get the same results as quart using standard python websockets.
I think everything is set up correctly, but the Dash-Extensions WebSocket doesn’t receive the message.
What is going wrong here?
import websockets # pip install websockets
import threading
import asyncio
from dash_extensions import WebSocket
from dash_extensions.enrich import html, dcc, Output, Input, DashProxy
#########################################################################
# DASH STUFF
update_graph = """
function(msg) {
if(!msg){
return {};
} // no data, just return
const data = JSON.parse(msg.data); // read the data
return data;
}; // plot the data
"""
dash_app = DashProxy(__name__)
dash_app.layout = html.Div([
WebSocket(id="ws", url=f"ws://127.0.0.1:5000/random_data"),
html.Div(['POPO'],id="graph")
])
dash_app.clientside_callback(update_graph, Output("graph", "children"), Input("ws", "message"))
#########################################################################
# WEBSOCKET STUFF
async def bogus(websocket, path):
async for data in websocket:
print(f">> Received: {data} {path}")
def run_ws_server():
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
ws_server = websockets.serve(bogus, '127.0.0.1', 5000)
loop.run_until_complete(ws_server)
loop.run_forever()
loop.close()
async def send_receive_ws_message(uri, data):
async with websockets.connect(uri) as websocket:
await websocket.send(data)
#reply = await websocket.recv()
#print(f"The reply is: '{reply}'")
#########################################################################
# SIMULATE MAIN PROGRAM
if __name__ == "__main__":
# STARTUP DASH + WS THREAD
# daemon dash_app thread:
threading.Thread(target=dash_app.run_server, kwargs={'host':'127.0.0.1','port':8050,'debug':False}, daemon=True).start()
# daemon ws_server thread:
threading.Thread(target=run_ws_server, daemon=True).start()
# SOMEWHERE INSIDE THE MAIN PROGRAM
import time, random
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
while True:
loop.run_until_complete(send_receive_ws_message(f'ws://127.0.0.1:5000/random_data', f'HURAY : {random.random()}'))
time.sleep(2)
loop.close()
Or in short:
@Emil : How to run the dash extensions WebSocket Example with standard websockets instead of Quart?