Shu's Garden - dash
type: channel
link: https://www.sitstars.com/tag/dash/
items: Dash实现数据推送与实时更新
items: python web可视化框架Dash介绍与使用

Dash实现数据推送与实时更新
type: item
date: 2021-04-02T00:43:00+08:00
description: 前言最近遇到了个需求，需要接收数据并且可视化展示出来，数据格式为DataFame。这个用Dash很容易实现，但实时更新就难搞了。Dash官方有定时刷新的组件，读取倒是不难，难点在于如何推送数据。经过这两天摸索，我找出了三个解决方案。存储到本地磁盘Dash官方有dash_core_components.Interval组件，这是一个计时器，可以设定时间间隔循环刷新页面。那么很自然的想法，我把生成的数据存到本地，然后网页不断刷新读取就行了。根据前一篇文章的经验，我们知道feather格式最适合小规模的dataframe的写入与读取，有了这一点，很容易就可以写出代码。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推送到内存中首先需要开一个端口用于发送数据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。# 其他代码省略 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')这个方案其实比较完美了，而且也符合我对前后端分离的粗浅认知。但还是有些不足，…

python web可视化框架Dash介绍与使用
type: item
date: 2021-01-19T22:31:32+08:00
description: 前言之前工作的时候，需要写一个日内交易信号监控软件，预计的功能是实时更新数据，出现信号时有提示功能（比如颜色变化和声音提醒）。如果可能的话最好也有可视化功能。我第一时间就想到了plotly同家出品的Dash，它是一个python Web可视化框架库，之前就有兴趣学，但是因为懒所以一直没有入手。需求来了才开始看文档，边看边翻译、实践，花了几天就写出了一个简单的网站。我个人还是挺满意的，所以也打算出一期教程介绍一下Dash。先把之前翻译的文档放上来把，之后有时间就讲一些高级用法。下文均翻译自https://dash.plotly.com/，算是一些比较基础的用法，有些地方可能是机翻的，最好还是去官网看。如果你有html和plotly基础，那入门应该会相当快，没有也没关系，我就不懂html，仿照着官网例子也能写。安装pip install dash布局基本用法首先，使用以下代码创建一个名为 app.py 的文件。import dash import dash_core_components as dcc import dash_html_components as html import plotly.express as px import pandas as pd external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css'] app = dash.Dash(__name__, external_stylesheets=external_stylesheets) # assume you have a "long-form" data frame # see https://plotly.com/python/px-arguments/ for more options df = pd.DataFrame({ "Fruit": ["Apples", "Oranges", "Bananas", "Apples", "Oranges", "Bananas"], "Amount": [4, 1, 2, 2, 4, 5], "City": ["SF", "SF", "SF", "Montreal", "Montreal", "Montreal"] }) fig = px.bar(df, x="Fruit", y="Amount", color="City", barmode="group") app.layout = html.Div(children=[ html.H1(children='Hello Dash'), html.Div(children=''' Dash: A web application framework for Python. '''), dcc.Graph( id='example-graph', figure=fig ) ]) if __name__ == '__main__': app.run_server(debug=True)然后运行程序$ python app.py访问 http://127.0.0.1:8050/效果如下： 注意：布局由一个“组件”树组成，比如 html.Div 和 dcc.Graph。对于每个 HTML 标记，dash_html_components 库都有一个组件。html.H1(children='Hello Dash')组件在应用程序中生成一个 Hello Dash HTML 元素。并非所有组件都是纯 HTML。dash_core_components 是可交互式高级组件，通过 React.js 库用 JavaScript、HTML 和 CSS 生成。每个组件都是通过关键字属性来描述的。dash 是声明式语法：主要通过这些属性描述应用程序。children 属性是特殊的。按照惯例，它总是第一个属性，这意味着您可以忽略它：html.H1(children='Hello Dash') 等价于 html.H1('Hello Dash')。它还可以包含字符串、数字、单个组件或组件列表。应用程序中的字体看起来与此处显示的字体略有不同。此应用程序使用自定义 CSS 样式表来修改元素的默认样式。您可以在 https://dash.plotly.com/external-resources 中了解更多信息，但现在您可以使用external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css'] app = dash.Dash(__name__, external_stylesheets=external_stylesheets)获得和示例相同的样式。…