Dash Plotly实时更新图表无法在浏览器自动刷新问题
问题
用Python的Plotly Dash开发实时加密货币追踪器,每分钟从API获取数据更新图表,但浏览器中图表无法自动刷新,必须手动操作(如平移图表)才会显示更新。控制台每分钟打印更新时间戳,确认数据获取和内部更新逻辑正常,但前端无自动更新。
原因分析
当前代码在回调中每次返回一个全新的dcc.Graph组件,Dash的组件渲染机制对重复创建同ID组件的更新支持不佳;另外animate=True参数会启用Plotly的动画过渡,反而可能阻碍全量数据更新的即时渲染。
解决方案
- 将
dcc.Graph直接放在布局中,而非通过回调返回组件 - 回调直接更新
dcc.Graph的figure属性,而非重新创建组件 - 移除
animate=True参数,避免动画逻辑干扰数据更新
修改后的代码
import os import datetime import pandas as pd import ccxt import plotly.graph_objs as go from dash import Dash, dcc, html from dash.dependencies import Input, Output symbol = 'BTC/USDT' timeframe = '5m' exchange = ccxt.binance({ 'rateLimit': 1200, 'enableRateLimit': True, }) def fetch_historical_data(symbol, timeframe, start_time, end_time): historical_data = exchange.fetch_ohlcv(symbol, timeframe, exchange.parse8601(start_time), exchange.parse8601(end_time)) return historical_data app = Dash(__name__) # 布局直接包含dcc.Graph,不再通过回调返回 app.layout = html.Div(children=[ html.H1(children=f'{symbol} {timeframe} Chart'), dcc.Interval(id='graph-update', interval=60 * 1000, n_intervals=0), html.Button('Refresh', id='refresh-button', n_clicks=0), # 直接定义Graph组件,ID固定 dcc.Graph(id='live-graph') ]) # 回调输出改为Graph的figure属性 @app.callback(Output('live-graph', 'figure'), [Input('graph-update', 'n_intervals'), Input('refresh-button', 'n_clicks')]) def update_graph(interval, n_clicks): print("Update graph function called") current_time = datetime.datetime.now(datetime.timezone.utc) print(f"Current time: {current_time}") local_time = current_time + datetime.timedelta(hours=0) end_time = local_time.strftime("%Y-%m-%dT%H:%M:%SZ") start_time = (local_time - datetime.timedelta(hours=5)).strftime("%Y-%m-%dT%H:%M:%SZ") print(f"Fetching historical data from {start_time} to {end_time}") data = fetch_historical_data(symbol, timeframe, start_time, end_time) print(f"Fetched {len(data)} data points") timestamps = [kline[0] for kline in data] dates = [datetime.datetime.fromtimestamp(timestamp / 1000) for timestamp in timestamps] df = pd.DataFrame(data, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume']) df['timestamp'] = dates df.set_index('timestamp', inplace=True) print(f"DataFrame created with {len(df)} rows") fig = go.Figure(data=[go.Candlestick(x=df.index, open=df['open'], high=df['high'], low=df['low'], close=df['close'])]) fig.update_layout(title=f'{symbol} {timeframe} Chart (Last update: {local_time.strftime("%Y-%m-%d %H:%M")})', yaxis_title='Price') print("Figure created") # 直接返回figure对象,而非组件 return fig if __name__ == '__main__': app.run_server(debug=True)
额外说明
- 这种方式符合Dash的更新逻辑:组件实例保持不变,仅更新其数据属性,前端会自动触发渲染
- 若需要保留动画效果,可改用
fig.update_layout(transition_duration=500)来设置平滑过渡,而非依赖animate=True
内容的提问来源于stack exchange,提问作者Fallyed
相关产品推荐
相关产品推荐

