Python Dash - 如何在@app.callback中传递参数

Python Dash - how to pass parameters in @app.callback

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

在代码中有一个关键部分允许 app.call 返回知道输入和输出是什么:

@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 调用它。

可能吗?

更新 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 是更新文本部分(return 是 html.Span() 和 .Br 的列表()s) 和 update_graph_live returns a go.Figure object).

然而,当我 运行 这个页面没有 return 任何图表或文本要更新时,点击右下角的“回调”,我看到 children 指向 null(即使我可以看到它作为 'live-update-text-PARAM' 传入并且我可以确认 update_metrics 名称的有效输入)。

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

更新 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

我看到的第一个问题是您有多个 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]
]