Summary
I’m trying to create a streamlit app that is the same for every user. What do I mean by this? This wont be interactive and shown data shouldnt change depending on the user. As shown in the code snippet, I open a WebSocket Client to receive data from another script I have, this data will be plotted using different streamlit functions so that the user can visualize.
The problem starts when you open the site twice, this is a problem because streamlit tries to open another websocket with the same port. For what is worth, I’m trying to create a streamlit app that updates every time it received more data in the websocket.
Steps to reproduce
Code snippet:
socket_ran = False
# Setup the WebSocket
async def websocket_client(websocket, path):
async for message in websocket:
on_message(message)
async def server_handler():
async with websockets.serve(websocket_client, "0.0.0.0", 5255) as server:
await asyncio.Future()
def run_server():
if not socket_ran:
asyncio.run(server_handler())
else:
print("Called Again")
ws_thread = threading.Thread(target = run_server)
ws_thread.start()
def _setup(name, ticker, date, status, variables):
# Strategy Name
st.session_state.name
# Ticker
st.session_state.ticker.name = ticker["name"]
st.session_state.ticker.timeframe = ticker["timeframe"]
st.session_state.ticker.exchange = ticker["exchange"]
# Strategy Date
st.session_state.date.start = date["from"]
st.session_state.date.end = date["to"]
# Process Status
st.session_state.status = status
# Variables List
st.session_state.variables = variables
#? Example : Type : Setup
{
"type":"setup",
"name":"Luda Kelt",
"ticker":{
"name":"BTCUSD.P",
"timeframe": "30m",
"exchange": "ByBit"
},
"date":{
"from":"",
"to":""
},
"status":"pending",
"variables": [
{
"name":"",
"from":"",
"to":"",
"step":""
},
{
"name":"",
"from":"",
"to":"",
"step":""
}
]
}
def _info(progress, status, eta, data):
# Progress %
st.session_state.progress = progrss
# Status
st.session_state.status = status
# Estimated Time
st.session_state.eta = eta
# Combination Data
st.session_state.data = data
#? Example : Type : Data
{
"type":"data",
"progress":"34",
"status":"Initializing",
"eta":"3 hours 22 minutes",
"data": {
"screenshot":"",
"overview":{},
"performance_summary":""
}
}
def on_message(message):
if message["type"] == "setup":
_setup(
name = message["name"],
ticker = message["ticker"],
date = message["date"],
status = message["status"],
variables = message["variables"]
)
elif message["type"] == "data":
_info(
progress = message["progress"],
status = message["status"],
eta = message["eta"],
data = message["data"]
)
def page_setup():
# Page config
st.set_page_config(
page_title = "Testing",
layout = "wide",
initial_sidebar_state = "expanded"
)
page_setup()
Expected behavior:
Only one WebSocket should open, and every time new data is received in the websocket, those st.session_state attributes update, so that in future code, new data is shown to the user every time the websocket receives new data (hope this makes sense)
Actual behavior:
Two WebSocket Clients are being opened, and since you cant open a single port more than once, this raises an error.
Debug info
- Streamlit version: 1.2
- Python version: 3.10
- OS version: Windows 10
- Browser version: Chrome
Requirements file
threading
websockets
asyncio
Additional information
Please feel free to ask for more information, I’ll kindly provide it. Thanks in advance for your help.