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更简洁:
- 在app.py中定义全局Store:
dcc.Store(id='global-store-data-BS', storage_type="session")
- 修改pg2.py的回调输出目标为
'global-store-data-BS',其他页面可通过Input('global-store-data-BS', 'data')直接获取共享数据。
注意事项
- 全局状态类在多用户场景下会共享数据,生产环境需结合用户会话标识(如Cookie)或使用
dcc.Store的session隔离特性。 - 回调参数为请求级局部变量,禁止直接将其作为模块属性访问。
内容的提问来源于stack exchange,提问作者Sanan jafar
相关产品推荐
相关产品推荐

