【发布时间】:2022-01-05 18:16:10
【问题描述】:
我正在尝试使用来自我制作的 websocket 服务器的数据更新在我的 web 浏览器中打开的 Dash 图表。 我对 websocket 部分没有任何问题。我的服务器将我添加到列表中的数据发送到客户端,并将此列表转换为 pandas DataFrame 对象。然后将此对象添加到 multiprocess.Queue。
在来自 dcc.Interval 的 Dash 回调中,我从前一个队列中获取数据(这部分似乎工作,因为我可以正确打印数据)并更新我的图表。
但是我浏览器中的图表没有更新。我没有在我的 python 代码或浏览器控制台中看到任何错误。 (我尝试使用 Firefox、Chrome 和 Brave)
我的 python 控制台在每个回调间隔打印dash-update-component HTTP/1.1" 200 - 和我的数据,选项卡名称是Updating...
更糟糕的是,有时我可以看到一个或 10 个数据正确显示,然后什么都没有,而无需更改代码,只需重新启动我的代码...
这里是代码(客户端):
import multiprocess as mp
import threading
import dash
from dash.dependencies import Output, Input
from dash import dcc
from dash import html
import plotly.graph_objs as go
from socket import *
import time
import json
import pandas as pd
from datetime import datetime
FLAG_QUIT = False
FLAG_ASK_DATA = False
MAX_SIZE = 10
queue = mp.Queue()
datas = []
app = dash.Dash(__name__)
app.layout = html.Div(
[
html.H4('Live Chart'),
dcc.Graph(id='live-update-graph', animate =True),
dcc.Interval(
id='interval-component',
interval=200,
n_intervals=0
)
]
)
@app.callback(Output('live-update-graph', 'figure'),
[Input('interval-component', 'n_intervals')])
def update_graph(n):
df = queue.get()
print(df)
fig = go.Scatter(x=df.index, y = df['Data'])
return fig
# function for receiving message from client
def send_to_server(clsock):
global FLAG_QUIT
global FLAG_ASK_DATA
while True:
try:
if FLAG_QUIT == True:
break
if FLAG_ASK_DATA:
time.sleep(0.5)
clsock.sendall("ok".encode())
except Exception as ex:
print(str(ex))
# function for receiving message from server
def recv_from_server(clsock):
global FLAG_QUIT
global FLAG_ASK_DATA
while True:
try:
data = clsock.recv(1024).decode()
if data == 'q':
print('Closing connection')
FLAG_QUIT = True
break
process_data(data)
FLAG_ASK_DATA = True
except Exception as ex:
print(str(ex))
def process_data(data):
global datas
global queue
process_websocket_data(data)
datas_dataframe = convert_data_to_dataframe(datas)
queue.put(datas_dataframe)
def convert_data_to_dataframe(data):
data_frame = pd.DataFrame(data)
data_frame = data_frame.drop_duplicates(0)
data_frame_date = data_frame[0]
final_date = []
for time in data_frame_date.unique():
readable = datetime.strptime(time, '%Y-%m-%d-%H-%M')
final_date.append(readable)
data_frame.pop(0)
dataframe_final_date = pd.DataFrame(final_date)
dataframe_final_date.columns = ['Date']
final_dataframe = data_frame.join(dataframe_final_date)
final_dataframe.set_index('Date', inplace = True)
final_dataframe.columns = ['Data']
return final_dataframe
def process_websocket_data(raw_data):
data_json = json.loads(raw_data)
data = [data_json['Date'],data_json['Data']]
datas.append(data)
while len(datas) > MAX_SIZE:
datas.pop(0)
def main():
threads = []
HOST = 'localhost'
PORT = 8765
clientSocket = socket(AF_INET, SOCK_STREAM)
connected = False
while not connected:
try:
print("Waiting connecting server...")
time.sleep(1)
clientSocket.connect((HOST, PORT))
connected = True
except :
pass
print('Client is connected to a chat sever!\n')
clientSocket.send('start'.encode())
t_send = threading.Thread(target=send_to_server, args=(clientSocket,))
t_rcv = threading.Thread(target=recv_from_server, args=(clientSocket,))
t_send.start()
t_rcv.start()
if __name__ == '__main__':
main()
app.run_server()
我编码错误或遗漏了什么?
编辑: 这是我在回调 update_graph(n) 方法中从队列中得到的数据。
Data
Date
2019-09-16 10302.00
2019-09-23 8061.98
2019-09-30 8042.08
2019-10-07 7851.01
2019-10-14 8274.33
2019-10-21 8218.23
2019-10-28 9534.37
2019-11-04 9197.86
2019-11-11 9041.31
2019-11-18 8504.13
我还尝试用 int 列表而不是日期列表替换我的 X 轴,但结果是相同的。不提神。
提前致谢。
【问题讨论】:
-
我敢打赌这是因为你的间隔太快了。 200 毫秒可能不足以让网络请求和回调在下一个间隔触发之前完成,这会重新启动回调。尝试将其设置为 20000 (20s) 之类的值来启动,看看它是否有效,然后仔细调整它,看看你能以多快的速度可靠地让它运行。
-
@coralvanda 感谢您的回复。不幸的是,我按照您的建议尝试了更大的间隔,但结果是一样的:我的浏览器中没有刷新。也许我试图实现我的应用程序的方式是完全错误的。我不熟悉 Dash。
-
如果你调试,或者添加一些
print语句,你能看到你的数据框在回调期间是什么样子的吗?这可能有助于指导解决方案。 -
@coralvanda 我用回调中获得的数据和我做的测试编辑了我的帖子,但没有成功。
-
好的,你有数据了,很好。关于如何设置散点图的问题可能是问题所在。您可以尝试硬编码一个测试 df 来玩。此外,您可以尝试在
dcc.Graph的布局中设置figure={},因为有时没有定义道具会很有趣。
标签: python websocket plotly-dash