【发布时间】:2022-01-07 15:40:23
【问题描述】:
我遇到了 dash/plotly 的问题。我有一个带有输入框、按钮和图形区域的 html 页面。按下按钮后,我使用回调来更新图形(基于输入框条目)。但是,当我第一次加载我的页面时,尽管输入框为空,但似乎正在强制评估回调函数。因此我得到一个“回调错误更新...”。
这是我的代码:
layout = html.Div([
dbc.Container([
dbc.Row([
dbc.Col(html.H1("1Y Stock Plot", className="text-center")
, className="mb-5 mt-5")
]),
html.Div([
dcc.Input(id='stockplot_symbol', placeholder='enter a stock ticker'),
html.Button("Plot", id='submit_stockplot', n_clicks=0),
]),
html.Div(id='output-graph')
])
])
和回调:
@app.callback(Output('output-graph', 'children'), #'stock_plot_graph', 'figure'),
[Input('submit_stockplot', 'n_clicks')],
[State('stockplot_symbol', 'value')]
)
def update_stockplot(n_clicks, symbol):
if n_clicks is not None:
ticker = str(symbol).upper()
df = yf.Ticker(ticker).history(period='1y', interval='1d')
fig = make_subplots(rows=2, cols=1, shared_xaxes=True, vertical_spacing=0.1, row_heights=[0.7, 0.2])
op = df['Open'].astype(float)
hi = df['High'].astype(float)
lo = df['Low'].astype(float)
cl = df['Close'].astype(float)
vo = df['Volume'].astype(float)
upper, middle, lower = talib.BBANDS(cl, timeperiod=10, nbdevup=2, nbdevdn=2)
fig.add_trace(go.Candlestick(x=df.index,
open=op,
high=hi,
low=lo,
close=cl, name=symbol), row=1, col=1)
fig.add_trace(go.Scatter(x=df.index, y=upper, name='Upper Band'), row=1, col=1)
fig.add_trace(go.Scatter(x=df.index, y=middle, name='Middle Band'), row=1, col=1)
fig.add_trace(go.Scatter(x=df.index, y=lower, name='Lower Band'), row=1, col=1)
fig.add_trace(go.Bar(x=df.index, y=vo, name='volume'), row=2, col=1)
fig.update_layout(xaxis_rangeslider_visible=False,
height=800,
xaxis=dict(type="date"),
hovermode='x unified'
)
return dcc.Graph(id='stock_plot_graph', figure=fig)
else:
return dash.exceptions.PreventUpdate
我确实在布局中将 n_clicks 设置为 0,但是 dash/plotly 以某种方式强制评估 if/else 语句中的内容,并且由于输入框中没有任何内容,因此数据框是空的,因此这会创建一个当我调用 talib.BANDS 时出现问题(这是函数 dash/plotly 抱怨回调错误更新... df 为空)
我的想法是仅在单击按钮时才更新或绘制图形区域。这在第一次调用后可以正常工作,但在第一次加载页面时就不行了。我尝试使用 if 语句来测试输入框是否为空,但得到相同的 callabck 错误。我可以设置一个初始/默认值来避免这种情况,但这对于我想做的事情来说并不是最佳的。我不想让回调中的函数在虚拟输入上进行评估,因为稍后该函数的处理时间不会像上述情况那样快。
你如何避免这种情况?
【问题讨论】: