Dash Plotly:通过dcc.Upload上传CSV至dcc.Store并展示表格的代码问题求助
修复你的Dash上传-存储-展示表格代码
我帮你排查出几个关键问题,修复后代码就能正常运行了:
问题分析
- 初始状态未处理:页面加载时,
upload-data的contents是None,直接调用contents.split(',')会抛出AttributeError - 多文件上传的类型问题:你设置了
multiple=True,所以contents是一个列表(而非单个字符串),直接对列表调用split肯定会出错 - 存储数据为空的情况:第二个回调中,当
dcc.Store还没有数据时,stored_data是None,直接用pd.read_json会报错
修复后的完整代码
import base64 import datetime import io import dash from dash.dependencies import Input, Output, State from dash import dcc, html, dash_table import pandas as pd external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css'] app = dash.Dash(__name__, external_stylesheets=external_stylesheets) app.layout = html.Div([ dcc.Upload( id='upload-data', children=html.Div([ 'Drag and Drop or ', html.A('Select Files') ]), style={ 'width': '100%', 'height': '60px', 'lineHeight': '60px', 'borderWidth': '1px', 'borderStyle': 'dashed', 'borderRadius': '5px', 'textAlign': 'center', 'margin': '10px' }, # Allow multiple files to be uploaded multiple=True ), dcc.Store(id='store'), html.Div(id='output-data-upload'), ]) # Goal here is to store the csv from upload into dcc.Store @app.callback(Output('store', 'data'), Input('upload-data', 'contents'), State('upload-data', 'filename'), State('upload-data', 'last_modified'), prevent_initial_call=True) # 阻止初始回调触发 def update_output(contents, list_of_names, list_of_dates): # 处理多文件情况,这里我们只取第一个上传的文件 if contents is not None and len(contents) > 0: content_type, content_string = contents[0].split(',') decoded = base64.b64decode(content_string) df = pd.read_csv(io.StringIO(decoded.decode('utf-8'))) return df.to_json(date_format='iso', orient='split') return None # 如果没有有效数据,返回None # Goal here is to then extract dataframe from dcc.store by reading json and output a table @app.callback( Output('output-data-upload', 'children'), Input('store', 'data') ) def output_from_store(stored_data): # 先判断存储的数据是否存在 if stored_data is None: return html.Div("请上传CSV文件以查看表格") df = pd.read_json(stored_data, orient='split') return html.Div([ dash_table.DataTable( df.to_dict('records'), [{'name': i, 'id': i} for i in df.columns], page_size=10 # 可选:设置每页显示行数,优化体验 ), html.Hr(), # horizontal line ]) if __name__ == '__main__': app.run_server(debug=True) # 开启debug模式方便调试
关键修改点说明
- 添加
prevent_initial_call=True到第一个回调,避免页面加载时触发回调导致错误 - 对
contents进行非空和长度判断,处理多文件上传的列表类型,这里选择只处理第一个文件(如果需要支持多文件合并,可以扩展逻辑) - 在第二个回调中先判断
stored_data是否为None,避免空值报错,同时给用户提示信息 - 可选:开启debug模式,方便开发时查看错误信息
内容的提问来源于stack exchange,提问作者ninja-k
相关产品推荐
相关产品推荐

