Dash实现数据推送与实时更新

2,081次阅读
没有评论

## 前言

最近遇到了个需求,需要接收数据并且可视化展示出来,数据格式为DataFame。这个用Dash很容易实现,但实时更新就难搞了。Dash官方有定时刷新的组件,读取倒是不难,难点在于如何推送数据。经过这两天摸索,我找出了三个解决方案。

## 存储到本地磁盘

Dash官方有`dash_core_components.Interval`组件,这是一个计时器,可以设定时间间隔循环刷新页面。那么很自然的想法,我把生成的数据存到本地,然后网页不断刷新读取就行了。根据[前一篇文章](https://www.sitstars.com/archives/113/)的经验,我们知道feather格式最适合小规模的dataframe的写入与读取,有了这一点,很容易就可以写出代码。

“`python
import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_table # 渲染表格的插件
from dash.dependencies import Input, Output

external_stylesheets = [‘https://codepen.io/chriddyp/pen/bWLwgP.css’]

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div(
html.Div([
html.H4(‘实时更新数据’),
html.Div(id=’live-update-text’),
dash_table.DataTable(id=’live-update-table’),
dcc.Interval(
id=’interval’,
interval=5*1000, # 5秒钟间隔
n_intervals=0
)
])
)

@app.callback([Output(“live-update-table”, “data”)],
[Input(“interval”, “n_intervals”)])
def make_table(n):
df = pd.read_feather(‘log.feather’)
return df.to_dict(‘records’)
“`

当然,还需要另外开一个进程用于存储df到feather。

测试了一段时间,发现feather读写有bug:当写入的同时读取,就会报错,从而中断计时器的运行,必须手动刷新网页才能重新开始更新。这就不行了,于是我的同事想出了另外一种解决方案:通过ZMQ推送到内存中

## 通过ZMQ推送到内存中

首先需要开一个端口用于发送数据

“`python
import zmq
import time
import random
import numpy as np
import pandas as pd

context = zmq.Context()
socket = context.socket(zmq.PUB)
socket.bind(“tcp://*:5411”)

while True:
df = pd.DataFrame(data=np.random.normal(0, 1, [2, 3]))
socket.send_pyobj(df)
time.sleep(1)
“`

然后上述代码中的`make_table`就可以直接读取内存中的数据,这样速度更快,而且不会产生读写冲突bug。

“`python
# 其他代码省略

def create_zmq_socket(zmq_port=”5411″):
“””连接ZMQ服务”””
context = zmq.Context()
zmq_socket = context.socket(zmq.SUB)
zmq_socket.connect(“tcp://localhost:%s” % zmq_port)
zmq_socket.setsockopt_string(zmq.SUBSCRIBE,”) # 消息过滤
return zmq_socket

def recv_zmq(listen_port=”5411″):
“””从ZMQ中接受数据”””
with create_zmq_socket(listen_port) as socket:
msg = socket.recv_pyobj()
return msg

@app.callback([Output(“live-update-table”, “data”)],
[Input(“interval”, “n_intervals”)])
def make_table(n):
df = recv_zmq()
return df.to_dict(‘records’)
“`

这个方案其实比较完美了,而且也符合我对前后端分离的粗浅认知。但还是有些不足,最重要的一点就是,诸如PYQT这种库,都有相应的事件回调函数,只有有数据推送时才会更新,不需要实时刷新监听。我们这种方案,时间间隔太短可能会消耗更多资源,时间间隔长的话对低延时的业务又非常不利。如果能实现类似于PYQT这种回调触发更新的逻辑就好了。

## 通过调用API更新数据

由于计算机基础和网络通信等知识的欠缺,我一开始就走向了死胡同,找了很多个方法,都是基于“数据推送过来,触发Dash的回调”进行的。我甚至在考虑要不要把数据推送也写到网页代码里面,然后用`while True`循环。很明显这样是不行的,While循环会阻塞Dash的线程,结果就是网页根本启动不了。

查了很多资料,最后发现了[dash_devices](https://github.com/richlegrand/dash_devices)库,它对`Dash`进行了扩展,其中一个新功能就是可以直接在代码内部改变组件值,而无需通过函数回调。看到这个功能,我突然灵光一现,是不是可以在网页代码里写一个API,数据推送模块一旦要更新数据,就调用一下这个API,然后改变页面上某个隐藏控件的属性,并链式回调触发`make_table`函数,提醒它从ZQM中获取数据。(当然理论上Post直接更新也可以,但是我对Post传数据不太了解,所以目前是通过这种方式间接实现的)

因为Dash是基于Flask实现的,所以我们可以很容易绑定一个路由。完整代码如下:

“`python
import dash_devices
from dash_devices.dependencies import Input, Output, State
import dash_core_components as dcc
import dash_html_components as html
import dash_table
import zmq
import time
import random
import numpy as np
import pandas as pd

external_stylesheets = [‘https://codepen.io/chriddyp/pen/bWLwgP.css’]

app = dash_devices.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div(
html.Div([
html.H4(‘实时更新数据’),
html.Div(id=’live-update-text’),
dash_table.DataTable(id=’live-update-table’),
html.Div(id=’flag’,hidden=True),
])
)

@app.callback([Output(“live-update-table”, “data”)],
[[Input(“flag”, “children”)]])
def make_table(n):
df = recv_zmq()
return df.to_dict(‘records’)

def create_zmq_socket(zmq_port=”5411″):
“””连接ZMQ服务”””
context = zmq.Context()
zmq_socket = context.socket(zmq.SUB)
zmq_socket.connect(“tcp://localhost:%s” % zmq_port)
zmq_socket.setsockopt_string(zmq.SUBSCRIBE,”) # 消息过滤
return zmq_socket

def recv_zmq(listen_port=”5411″):
“””
接受数据
“””
with create_zmq_socket(listen_port) as socket:
msg = socket.recv_pyobj()
return msg

def get_count():
global count
count += 1
if count >= 10:
count = 0
return count

@app.server.route(‘/update_data’,methods = [‘get’,’post’])
def update_data():
app.push_mods({‘flag’: {‘children’: str(get_count())}})
return ‘请求成功’
“`

前半部分代码和上两章差不多,只不过用`dash_devices`替换掉了`dash`,核心在于最后的绑定路由。这样的话,在数据推送模块,每次推送新数据后,都可以get一下API,提醒网页更新数据。

“`python
import requests
requests.get(‘127.0.0.1:5000/update_data’)
“`Read More 

正文完
可以使用微信扫码关注公众号(ID:xzluomor)
post-qrcode
 0
评论(没有评论)

文心AIGC

2023 年 3 月
 12345
6789101112
13141516171819
20212223242526
2728293031  
文心AIGC
文心AIGC
人工智能ChatGPT,AIGC指利用人工智能技术来生成内容,其中包括文字、语音、代码、图像、视频、机器人动作等等。被认为是继PGC、UGC之后的新型内容创作方式。AIGC作为元宇宙的新方向,近几年迭代速度呈现指数级爆发,谷歌、Meta、百度等平台型巨头持续布局
文章搜索
热门文章
潞晨尤洋:日常办公没必要上私有模型,这三类企业才需要 | MEET2026

潞晨尤洋:日常办公没必要上私有模型,这三类企业才需要 | MEET2026

潞晨尤洋:日常办公没必要上私有模型,这三类企业才需要 | MEET2026 Jay 2025-12-22 09...
面向「空天具身智能」,北航团队提出星座规划新基准丨NeurIPS’25

面向「空天具身智能」,北航团队提出星座规划新基准丨NeurIPS’25

面向「空天具身智能」,北航团队提出星座规划新基准丨NeurIPS’25 鹭羽 2025-12-13 22:37...
钉钉又发新版本!把 AI 搬进每一次对话和会议

钉钉又发新版本!把 AI 搬进每一次对话和会议

钉钉又发新版本!把 AI 搬进每一次对话和会议 梦晨 2025-12-11 15:33:51 来源:量子位 A...
商汤Seko2.0重磅发布,合作短剧登顶抖音AI短剧榜No.1

商汤Seko2.0重磅发布,合作短剧登顶抖音AI短剧榜No.1

商汤Seko2.0重磅发布,合作短剧登顶抖音AI短剧榜No.1 十三 2025-12-15 14:13:14 ...
跳过“逐字生成”!蚂蚁集团赵俊博:扩散模型让我们能直接修改Token | MEET2026

跳过“逐字生成”!蚂蚁集团赵俊博:扩散模型让我们能直接修改Token | MEET2026

跳过“逐字生成”!蚂蚁集团赵俊博:扩散模型让我们能直接修改Token | MEET2026 一水 2025-1...
最新评论
ufabet ufabet มีเกมให้เลือกเล่นมากมาย: เกมเดิมพันหลากหลาย ครบทุกค่ายดัง
tornado crypto mixer tornado crypto mixer Discover the power of privacy with TornadoCash! Learn how this decentralized mixer ensures your transactions remain confidential.
ดูบอลสด ดูบอลสด Very well presented. Every quote was awesome and thanks for sharing the content. Keep sharing and keep motivating others.
ดูบอลสด ดูบอลสด Pretty! This has been a really wonderful post. Many thanks for providing these details.
ดูบอลสด ดูบอลสด Pretty! This has been a really wonderful post. Many thanks for providing these details.
ดูบอลสด ดูบอลสด Hi there to all, for the reason that I am genuinely keen of reading this website’s post to be updated on a regular basis. It carries pleasant stuff.
Obrazy Sztuka Nowoczesna Obrazy Sztuka Nowoczesna Thank you for this wonderful contribution to the topic. Your ability to explain complex ideas simply is admirable.
ufabet ufabet Hi there to all, for the reason that I am genuinely keen of reading this website’s post to be updated on a regular basis. It carries pleasant stuff.
ufabet ufabet You’re so awesome! I don’t believe I have read a single thing like that before. So great to find someone with some original thoughts on this topic. Really.. thank you for starting this up. This website is something that is needed on the internet, someone with a little originality!
ufabet ufabet Very well presented. Every quote was awesome and thanks for sharing the content. Keep sharing and keep motivating others.
热评文章
预见未来:96位前沿先锋超万字核心观点总结,抢抓未来产业新高地

预见未来:96位前沿先锋超万字核心观点总结,抢抓未来产业新高地

预见未来:96位前沿先锋超万字核心观点总结,抢抓未来产业新高地 henry 2025-12-11 10:27:...
Meta公开抄阿里Qwen作业,还闭源了…

Meta公开抄阿里Qwen作业,还闭源了…

Meta公开抄阿里Qwen作业,还闭源了… Jay 2025-12-11 11:48:25 来源:量子位 Ja...
MEET2026挤爆了,AI圈今年最该听的20+场演讲&对谈都在这

MEET2026挤爆了,AI圈今年最该听的20+场演讲&对谈都在这

MEET2026挤爆了,AI圈今年最该听的20+场演讲&对谈都在这 西风 2025-12-11 15:...
钉钉又发新版本!把 AI 搬进每一次对话和会议

钉钉又发新版本!把 AI 搬进每一次对话和会议

钉钉又发新版本!把 AI 搬进每一次对话和会议 梦晨 2025-12-11 15:33:51 来源:量子位 A...