【问题标题】:Python Dash - how to pass parameters in @app.callbackPython Dash - 如何在@app.callback 中传递参数
【发布时间】:2022-01-01 19:12:02
【问题描述】:

我正在尝试创建一个 Dash 示例,该示例可以通过使用此处的文档来利用实时更新:https://dash.plotly.com/live-updates

在代码中有一个关键部分可以让 app.call back 知道输入和输出是什么:

@app.callback(Output('live-update-text', 'children'),
              Input('interval-component', 'n_intervals')

这适用于一个组件,但是如果说我有五个不同的数据集要更新(都使用相同的逻辑),那么我自然希望像函数参数一样动态传递 @app.callback .即,理想情况下,如果我有 5 个输出,我可以这样做:

@app.callback(Output('live-update-text-MyParam', 'children'),
              Input('interval-component', 'n_intervals')

然后我可以使用 myParam = 1/2/3/4/5 来调用它。

有可能吗?

UPDATE 20220105:根据@coralvanda 和@EricLavault 的建议,这是我的想法:

def updateGraphsAndData(output, input):
    @app.callback([output['text'],
                   output['graph']],
                  [input['n_intervals'],input['name']])
    def updateGraphAndMetricForEach(n, name):
        return update_metrics(name), update_graph_live(name)

for param in lstParams:
    updateGraphsAndData(output={'text':Output(f'live-update-text-{param}','children'),'graph':Output(f'live-update-graph-{param}','figure')},
                        input={'n_intervals':Input(f'interval-component-{param}','n_intervals'),'name':Input(param, 'value')})

我正在尝试一次性更新图形和文本,update_metrics 是更新文本部分(返回 html.Span() 和 .Br()s 的列表),而 update_graph_live 返回一个 go.Figure对象)。

但是,当我运行此页面时,该页面不会返回任何要更新的图表或文本,并单击右下角的“回调”,我看到子项指向 null(即使我可以看到它是作为 'live-update-text-PARAM' 传入,我可以确认 update_metrics 以获取有效的名称输入)。

我还有什么遗漏的地方吗?

UPDATE 20220106:app.layout 代码的一部分:

dbc.Col([
                html.Div(id=f'live-update-text-{param1}'),
                dcc.Graph(id=f'live-update-graph-{param1}'),
                dcc.Interval(
                id=f'interval-component-{param1}',
                interval=2*1000, # in milliseconds
                n_intervals=0
                ),
            html.Hr(),
            ], width={'size': 4, 'offset': 0, 'order': 1}),

然后对 param1/param2/param3/param4/param5 重复此操作

【问题讨论】:

  • 查看this answer,这可能就是您想要的。
  • 为什么不直接有 5 个输出?或者,如果要动态更改组件的数量,您可以使用包含所有“live-update-text-X”组件的包装器,并使用单个输出来更新包装器的子级。
  • 谢谢@EricLavault,我认为你的回答在那里提出了一条很好的道路,所以基本上你的意思是在@app.callback 我可以做类似的事情:@app.callback(Output('live-update-text-1', 'children'),Output('live-update-text-2', 'children'),Output('live-update-text-3', 'children'),Output('live-update-text-4', 'children'),Output('live-update-text-5', 'children'), Input('interval-component', 'n_intervals')?这是我不知道的。
  • 我对包含所有 live-update-text-X 的包装器有点困惑,你的意思是我们可以在输出中返回一个列表并以某种方式解析 app.layout 部分中的列表代码?
  • 啊,没关系,我在@coralvanda 提供的链接上阅读了一些内容,我认为这可能是您的建议:stackoverflow.com/a/63255593/1528840,非常感谢,我想现在我可以弄清楚了: )

标签: python plotly-dash


【解决方案1】:

我看到的第一个问题是您有多个 dcc.Interval(每个活动组件一个),但这不是必需的,因为您每个间隔只需要一个调用来更新所有组件。

然后,由于所有要更新的元素都在同一个容器中(我假设您将 dbc.Col 放在 dbc.Row 中),您可以在回调中使用单个输出来更新容器子级。

所以在你的布局中你可以这样做:

dcc.Interval(
    id='interval-component',
    interval=2*1000,  # in milliseconds
    n_intervals=0
),

dbc.Row(id="live-update-wrapper", children=[
    dbc.Col([
            html.Div(id=f'live-update-text-{param}'),
            dcc.Graph(id=f'live-update-graph-{param}'),
            html.Hr(),
        ],
        width={'size': 4, 'offset': 0, 'order': 1}
    ) for param in [1, 2, 3, 4, 5]
]),

对于回调使用相同的逻辑(只需获取所需的数据并将它们与参数 id 一起相应地插入):

@app.callback(
    Output("live-update-wrapper", "children"),
    Input("interval-component", "n_intervals"))
def updateGraphsAndData(n):
    return [
        dbc.Col([
                html.Div(id=f'live-update-text-{param}'),
                dcc.Graph(id=f'live-update-graph-{param}'),
                html.Hr(),
            ],
            width={'size': 4, 'offset': 0, 'order': 1}
        ) for param in [1, 2, 3, 4, 5]
]

【讨论】:

  • 非常感谢 Eric,现在我开始理解你所说的包装器是什么意思,基本上你甚至可以包装要返回的 dbc.Col(我更多的是考虑一个包装器来返回实际的图和文字)。感谢您的所有帮助!
  • @AZhu 请注意,如果您需要图表的平滑过渡,则每个 figure 需要一个输出(参见我的第一条评论)+ 每个文本组件一个输出,但它仍然可以使用一个回调来完成。
  • 感谢您的好意建议,如果我理解正确,您的意思是,您将拥有 Output(f"live-update-wrapper-{param}", "children") 之类的东西,而不是 Output("live-update-wrapper", "children"),
  • 不,在这种情况下(您需要每个图形平滑过渡),包装器不是一个选项,因为它会重绘布局的那部分。我的意思是每个图表一个 Output(f'live-update-graph-{param}", "figure"),每个文本 Div 一个。您的回调将返回与这些输出对应的列表[fig1, fig2, ..., fig5, txt1, txt2, ..., txt5]
  • 谢谢,我无法将返回作为列表工作(似乎我必须做 return fig1,fig2,fig3...txt1,...txt5 而不是 return [fig1,...fig5,txt1...txt5] 所以我最终只返回 fig, txt 但将它们包装在 @ 987654332@,不确定这是否是最优雅的做事方式,但目前这似乎可行。
猜你喜欢
  • 1970-01-01
  • 2020-03-03
  • 2022-01-04
  • 2016-02-08
  • 2021-10-31
  • 2018-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多