Plotly Dash仪表板加载卡顿:疑似代码存在Bug需排查
问题定位与修复方案
1. 初始空数据触发绘图报错
dcc.Store初始值设为空字典,首次回调生成空DataFrame后,K线图和折线图因缺少必要数据直接崩溃,导致仪表板无法加载。
修复:
初始化dcc.Store时直接传入初始数据,而非空字典:
dcc.Store(id="storage", storage_type="memory", data=update_data().to_dict("records")),
2. 下拉框未关联业务逻辑(可选优化)
代码中定义了股票下拉框,但未通过回调关联数据更新逻辑,当前始终固定获取USDJPY汇率数据。若需支持切换股票,补充以下修改:
- 给
update_data增加股票代码参数:
def update_data(ticker='USDJPY%3DX'): try: df = data.DataReader(ticker, data_source='yahoo', start=start, end=end).reset_index() return df except Exception as e: return pd.DataFrame(columns=['Date', 'Open', 'High', 'Low', 'Close'])
- 更新数据存储回调,加入下拉框输入:
@app.callback(Output("storage", "data"), Input("timer", "n_intervals"), Input("dropdown", "value")) def store_data(n_time, ticker): df = update_data(ticker[0]) return df.to_dict("records")
3. 折线图丢失日期轴信息
px.line(df.range_sma)仅传入数值序列,Plotly自动生成索引作为x轴,丢失原始日期信息,导致图表可读性极差。
修复:
明确指定x轴为Date列:
fig = px.line(df, x='Date', y='range_sma')
4. 增加异常捕获提升健壮性
数据获取失败时(如网络问题、股票代码错误),直接返回空DataFrame并在绘图回调中判断空值,避免整个仪表板崩溃:
在绘图回调中加入空值判断:
# 以K线图回调为例 def display_data(stored_dataframe): df = pd.DataFrame.from_records(stored_dataframe) if df.empty: return go.Figure() fig = go.Figure(data=[go.Candlestick(x=df['Date'], open=df['Open'], high=df['High'], low=df['Low'], close=df['Close'])]) return fig
完整修复代码
from dash import Dash, html, dcc, Input, Output, State import plotly.express as px import plotly.graph_objects as go import dash_bootstrap_components as dbc import pandas as pd from pandas_datareader import data import yfinance as yf yf.pdr_override() from datetime import date start = pd.to_datetime('2022-01-01') end = pd.to_datetime(date.today()) def update_data(ticker='USDJPY%3DX'): try: df = data.DataReader(ticker, data_source='yahoo', start=start, end=end).reset_index() return df except Exception as e: return pd.DataFrame(columns=['Date', 'Open', 'High', 'Low', 'Close']) app = Dash(__name__, external_stylesheets=[dbc.themes.LITERA]) app.layout = dbc.Container( [ dbc.Row( [dbc.Col([html.H1( "Daily Price", style={"textAlign": "center"}, ), dcc.Graph(id="price-chart", figure={})], width=12,lg=6), dbc.Col([html.H1( "10 Day SMA of Daily Range", style={"textAlign": "center"}, ), dcc.Graph(id="volatility-chart", figure={})], width=12,lg=6) ] ), dbc.Row( dbc.Col(dcc.Dropdown( id="dropdown", options=["AAPL", "TSLA", "MSFT", "USDJPY%3DX"], value=["TSLA"], style={"color": "green"} ), className="three columns"), ), dcc.Store(id="storage", storage_type="memory", data=update_data().to_dict("records")), dcc.Interval(id="timer", interval=1000 * 60, n_intervals=0), ] ) @app.callback(Output(component_id = "storage", component_property = "data"), Input(component_id = "timer", component_property = "n_intervals"), Input(component_id = "dropdown", component_property = "value")) def store_data(n_time, ticker): df = update_data(ticker[0]) return df.to_dict("records") @app.callback(Output(component_id = "price-chart", component_property = "figure"), Input(component_id = "storage", component_property = "data")) def display_data(stored_dataframe): df = pd.DataFrame.from_records(stored_dataframe) if df.empty: return go.Figure() fig = go.Figure(data=[go.Candlestick(x=df['Date'], open=df['Open'], high=df['High'], low=df['Low'], close=df['Close'])]) return fig @app.callback(Output(component_id = "volatility-chart", component_property = "figure"), Input(component_id = "storage", component_property = "data")) def modify_data(stored_dataframe): df = pd.DataFrame.from_records(stored_dataframe) if df.empty: return px.line() df['range'] = df.High - df.Low df['range_sma'] = df.range.rolling(10).mean() fig = px.line(df, x='Date', y='range_sma') return fig if __name__ == "__main__": app.run_server(debug=True)
内容的提问来源于stack exchange,提问作者matsuo_basho
相关产品推荐
相关产品推荐

