dash/plotly 中的回调忽略 if 条件
callback in dash/plotly ignores if condition
我 运行 遇到了 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 错误。我可以设置一个 initial/default 值来避免这种情况,但这对于我想做的事情来说并不是最佳选择。我不想在虚拟输入上评估回调中的函数,因为稍后该函数的处理时间不会像上述情况那样快。
你如何避免这种情况?
My idea was to have the graph area being updated or drawn only when the button is clicked. This works fine after the first call but not when loading up the page for the first time.
如果您想避免在页面加载时执行回调,您可以将回调的 prevent_initial_call
属性设置为 True
。
All of the callbacks in a Dash app are executed with the initial value of their inputs when the app is first loaded. This is known as the "initial call" of the callback... You can use the prevent_initial_call attribute to prevent callbacks from firing when their inputs initially appear in the layout of your Dash application. This attribute applies when the layout of your Dash app is initially loaded, and also when new components are introduced into the layout when a callback has been triggered.
https://dash.plotly.com/advanced-callbacks#prevent-callbacks-from-being-executed-on-initial-load
我 运行 遇到了 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 错误。我可以设置一个 initial/default 值来避免这种情况,但这对于我想做的事情来说并不是最佳选择。我不想在虚拟输入上评估回调中的函数,因为稍后该函数的处理时间不会像上述情况那样快。
你如何避免这种情况?
My idea was to have the graph area being updated or drawn only when the button is clicked. This works fine after the first call but not when loading up the page for the first time.
如果您想避免在页面加载时执行回调,您可以将回调的 prevent_initial_call
属性设置为 True
。
All of the callbacks in a Dash app are executed with the initial value of their inputs when the app is first loaded. This is known as the "initial call" of the callback... You can use the prevent_initial_call attribute to prevent callbacks from firing when their inputs initially appear in the layout of your Dash application. This attribute applies when the layout of your Dash app is initially loaded, and also when new components are introduced into the layout when a callback has been triggered.
https://dash.plotly.com/advanced-callbacks#prevent-callbacks-from-being-executed-on-initial-load