You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Gunicorn部署含dcc.Interval与dcc.Location的Dash多页应用回调死循环问题

问题原因

回调不触发的原因

你最初的代码中,interval.py里的update_graphs回调是注册在interval.py独立实例化的Dash对象上的,而多页应用入口index.py使用的是app.py中定义的全局Dash实例,两个实例完全独立,全局实例并未注册interval.py中的回调,因此回调无法被触发。

无限循环的原因

你将interval.py中的独立Dash实例替换为导入全局app后,interval.app就指向了全局的Dash对象,而全局Dash对象的layout是你在index.py中定义的包含导航、dcc.Location、page-content容器的顶层布局。此时你在display_page回调中返回interval.app.layout,等于把整个顶层布局又嵌套进了page-content容器里,页面加载后会重复触发路径检测、嵌套布局,形成无限渲染循环。

解决方案

步骤1:修改interval.py

删除interval.py中独立实例化Dash对象的代码,导入全局app,将子页面布局定义为独立的layout变量,回调直接注册到全局app上即可,修改后代码如下:

import numpy as np
import dash
import pandas as pd
import plotly.express as px
from dash.dependencies import Output, Input
from dash import dcc
from dash import html
# 导入全局app
from app import app

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

# 子页面布局定义为独立变量,不要赋值给app.layout
layout = html.Div(className='row', children=[
    html.Div(children=[dcc.Graph(id='a-graph', style={'display': 'flex'}),
                       dcc.Graph(id='b-graph', style={'display': 'flex'}),
                       dcc.Interval(id='interval-component', interval=1000)])])

# 回调注册到全局app上
@app.callback(
    [
        Output('a-graph', 'figure'),
        Output('b-graph', 'figure')
    ],
    [
        Input('interval-component', 'n_intervals')
    ]
)
def update_graphs(n):
    print(f'callback happened: {n}')
    df = pd.DataFrame({"time":pd.Series(pd.date_range("1-nov-2021","2-nov-2021", freq="S")).sample(30), "bacteria_count":np.random.randint(0,500, 30), "bacteria_type":np.random.choice(list("AB"),30)})

    df["epoch_time_ms"] = df["time"].astype(int) / 1000
    df = df.sort_values("time")
    a_fig = px.line(df, x="time", y="bacteria_count", line_shape="hv", markers=True, color='bacteria_type')
    a_fig.update_traces(mode="markers+lines", hovertemplate=None)
    a_fig.update_layout(hovermode='x unified')

    b_fig = px.line(df, x="epoch_time_ms", y="bacteria_count", line_shape="hv", markers=True, color='bacteria_type')
    b_fig.update_traces(mode="markers+lines", hovertemplate=None)
    b_fig.update_layout(hovermode='x unified')
    return a_fig, b_fig

# 保留单文件运行的逻辑,独立测试时可正常运行
if __name__ == '__main__':
    local_app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
    local_app.layout = layout
    for callback in app.callback_map.values():
        local_app.callback(**callback['outputs'])(callback['callback'])
    local_app.run_server(debug=True)

步骤2:修改index.py中的页面返回逻辑

将display_page回调中返回interval.app.layout的代码,改为返回interval.layout即可,修改后对应部分代码如下:

@app.callback(Output('page-content', 'children'),
              Input('url', 'pathname'))
def display_page(pathname):
    if pathname == '/apps/interval':
        # 直接返回子页面的独立layout变量,不要调用全局app的layout
        return interval.layout
    else:
        return ''

修改完成后重启服务,即可正常触发回调,也不会出现无限循环问题。

内容的提问来源于stack exchange,提问作者HCSF

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 08:15:03