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

Dash应用跨页面共享变量报错:AttributeError 解决方案求助

Dash跨页面共享变量解决方案(针对AttributeError问题)

错误根源

n_clicks_b是pg2.py中update_output回调的局部参数,并非pg2模块的全局属性,因此app.py中直接调用pages.pg2.n_clicks_b会触发AttributeError。


方案一:全局状态类管理共享变量

通过创建全局状态类,统一存储跨页面需要共享的变量(如点击次数、上传文件数据),避免直接访问模块局部参数。

1. 创建全局状态文件(state_manager.py)

class AppState:
    def __init__(self):
        self.n_clicks_b = 0
        self.uploaded_files = {}  # 存储所有上传文件的结构化数据

# 初始化全局实例,跨模块共享
app_state = AppState()

2. 修改pg2.py代码

替换原全局变量,改用全局状态类存储数据,并更新点击次数:

import base64
import io
import pandas as pd
from dash import html, dbc, callback, Input, Output, State, PreventUpdate, dcc
from state_manager import app_state

def parse_contents_1(contents, filename, date, n_clicks_b):
    content_type, content_string = contents.split(',')
    decoded = base64.b64decode(content_string)
    try:
        if 'csv' in filename:
            df = pd.read_csv(io.StringIO(decoded.decode('utf-8')), skiprows=7)
            app_state.uploaded_files[filename] = df.to_dict('records')
        elif 'xls' in filename:
            df = pd.read_excel(io.BytesIO(decoded), skiprows=7)
            app_state.uploaded_files[filename] = df.to_dict('records')
    except Exception as e:
        print(e)
        return html.Div(['Yüklədiyiniz fayl formatı dəstəklənmir.'])
    
    fName = filename.split('_')[0] + ' ' + filename.split('_')[1]
    return dbc.Col([
        html.Div([
            html.H5(fName, id={"type":"dynamic-name", "index": n_clicks_b }),
            dcc.Slider(id={"type":"id_1", "index": n_clicks_b }, step=1)
        ])
    ], width=5)

@callback(
    [Output('output-dataBS', 'children'), Output('store-data-BS', 'data')],
    [Input('upload-data-BS', 'contents'), Input("dynamic-add-filter", "n_clicks")],
    [State('upload-data-BS', 'filename'), State('upload-data-BS', 'last_modified'), State("output-dataBS", "children")]
)
def update_output(list_of_contents, n_clicks_b, list_of_names, list_of_dates, children_bs):
    if list_of_contents is not None:
        # 更新全局状态中的点击次数
        app_state.n_clicks_b = n_clicks_b
        new_children = [
            parse_contents_1(c, n, d, n_clicks_b) for c, n, d in zip(list_of_contents, list_of_names, list_of_dates)
        ]
        # 注意:list.append返回None,需创建新列表更新子组件
        updated_children = children_bs + new_children if children_bs else new_children
        return updated_children, app_state.uploaded_files
    raise PreventUpdate

3. 修改app.py代码

通过全局状态实例获取点击次数,避免直接访问模块局部参数:

from dash import Dash, dcc, html, pages
from state_manager import app_state

app = Dash(__name__, use_pages=True)

app.layout = html.Div([
    # 其他布局组件
    dcc.Store(
        id={"type":'store-data-BS', "index": app_state.n_clicks_b},
        storage_type="session"
    ),
    pages.page_container
])

if __name__ == '__main__':
    app.run_server(debug=True)

方案二:简化dcc.Store用法(无需动态ID)

如果不需要按点击次数区分存储实例,直接使用全局ID的dcc.Store更简洁:

  1. 在app.py中定义全局Store:
dcc.Store(id='global-store-data-BS', storage_type="session")
  1. 修改pg2.py的回调输出目标为'global-store-data-BS',其他页面可通过Input('global-store-data-BS', 'data')直接获取共享数据。

注意事项

  • 全局状态类在多用户场景下会共享数据,生产环境需结合用户会话标识(如Cookie)或使用dcc.Store的session隔离特性。
  • 回调参数为请求级局部变量,禁止直接将其作为模块属性访问。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 05:05:39