Plotly Dash上传按钮无响应问题求助
Plotly Dash上传按钮无响应问题排查与解决
问题背景
数月前正常运行的Plotly Dash代码,当前点击Upload按钮无任何响应,无报错信息;复制官方Upload组件示例代码测试,问题依旧。
提交代码
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css'] app = Dash(__name__, external_stylesheets=external_stylesheets) # if deploy onto a server server = app.server # create a background template for plots templates = ['plotly', 'seaborn', 'simple_white', 'ggplot2', 'plotly_white', 'plotly_dark', 'presentation', 'xgridoff', 'ygridoff', 'gridon', 'none'] # create a blank figure to prevent plotly dash error when runnng the app, even though it still works without this. def blankfigure(): figure = go.Figure(go.Scatter(x=[],y=[])) figure.update_layout(template = None) figure.update_xaxes(showgrid = False, showticklabels = False, zeroline = False) figure.update_yaxes(showgrid = False, showticklabels = False, zeroline = False) return figure app.layout = html.Div([ # components for label and input content by user dbc.Row([dbc.Col(html.H1('Plotter App', style={'textAlign': 'center', "font-size":"60px"}))]), # title # components for upload file dbc.Row([dbc.Col(html.Label('Upload file') ,style={'textAlign': 'left',"font-size":"30px"})]), dbc.Row([dcc.Upload(id='upload-data',children=html.Div(['Drag and Drop or ',html.A('Select Files')]), style={ 'width': '30%', 'height': '60px', 'lineHeight': '60px', 'borderWidth': '1px', 'borderStyle': 'dashed', 'borderRadius': '5px', 'textAlign': 'center', 'margin': '10px' }, # Allow multiple files to be uploaded multiple=False) ]), html.Div(id='output-data-upload', children = ''), # component for radio button for show/hide table dbc.Row([dcc.RadioItems(id = 'show_hide_table_button', options = ['show_table', 'hide_table','show_plot'], value = 'hide')]), ]) def parse_contents(contents, file_name): # 'contents/filename' property is needed for callbacks content_type, content_string = contents.split(',') #print(content_type) decoded = base64.b64decode(content_string) #print(decoded) if 'csv' in file_name: # Assume that the user uploaded a CSV file df = pd.read_csv(io.StringIO(decoded.decode('utf-8'))) elif 'xls' in file_name: # Assume that the user uploaded an excel file df = pd.read_excel(io.BytesIO(decoded)) elif 'txt' in file_name: # Assume that the user uploaded an text file # 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte -> USE utf-16 df = pd.read_csv(io.StringIO(decoded.decode('utf-16')), delimiter = '\t') # \t separates columns separated by tabs return df @app.callback( Output('output-data-upload', 'children'), [Input('upload-data', 'contents'), # refer to first arg in upload_data_file() Input('upload-data', 'filename'), # refer to 2nd arg in upload_data_file() Input(component_id = 'show_hide_table_button', component_property = 'value')] # refer to 3rd arg in upload_data_file() #State('upload-data', 'last_modified'), #prevent_initial_call=True ) def upload_data_file(contents, file_name, display): show_table = html.Div() show_plot = html.Div() global uploaded_df if contents is not None: uploaded_df = parse_contents(contents, file_name) # dataframe object dropdown = uploaded_df.columns show_table = html.Div([ dbc.Row([dbc.Col([html.H5(file_name)])]), # show data table dbc.Row([dbc.Col([dash_table.DataTable(data=uploaded_df.to_dict('rows'), columns=[{"name": i, "id": i} for i in uploaded_df.columns])])]), ]) show_plot = html.Div([ # component for show dropdown options dbc.Row([dbc.Col(html.Label('Select x-axis from dropdown'), width=2), #width = between Cols dbc.Col(dcc.Dropdown(id = 'xaxis_column', options = dropdown, value = None)), dbc.Col(html.Label('Select x-axis from dropdown'), width=2), #width = between Cols dbc.Col(dcc.Dropdown(id = 'xaxis_column1', options = dropdown, value = None)), ]), dbc.Row([dbc.Col(html.Label('Select y-axis from dropdown'), width=2), dbc.Col(dcc.Dropdown(id = 'yaxis_column', options = dropdown, value = None, multi = True)), dbc.Col(html.Label('Select y-axis from dropdown'), width=2), dbc.Col(dcc.Dropdown(id = 'yaxis_column1', options = dropdown, value = None, multi = True)), ]), # component for output graph(s) when data is uploaded dbc.Row([dbc.Col(dcc.RadioItems(id='template', options = [{'label': k, 'value': k} for k in templates], value = None, inline=True)), dbc.Col(dcc.RadioItems(id='template1', options = [{'label': k, 'value': k} for k in templates], value = None, inline=True)), # grid style ]), # grid style html.Br(), # components for graph, graph options, and download data from plot (for two plots) dbc.Row([dbc.Col(dcc.Graph(id="graph", figure=blankfigure())), dbc.Col(dcc.Graph(id="graph1", figure=blankfigure())) ]), dbc.Row([dbc.Col(dcc.Dropdown(id = 'plot_type', options = ['scatter,','line','bar','box'], value = 'line', style={'font-size':20})), dbc.Col(dcc.Dropdown(id = 'plot_type1', options = ['scatter','line','bar','box'], value = 'line', style={'font-size':20})), ]), ]) # connecting radio button options with output of upload button if display == 'show': return show_table if display == 'hide_table': return None if display == 'show_plot': return show_plot
排查方向及解决方案
依赖版本冲突
检查Dash及相关依赖(dash-core-components、dash-html-components、dash-bootstrap-components等)的版本,数月前的版本可能与当前环境不兼容。建议锁定之前可用的版本,或逐步升级排查。浏览器缓存干扰
清除浏览器缓存,或使用无痕模式测试,避免旧的静态资源导致的异常。代码逻辑缺陷
- RadioItems初始值设为
'hide',但回调判断逻辑中无对应分支,导致上传后无输出反馈。需将初始值改为'hide_table',或补充display == 'hide'的处理分支。 parse_contents函数对txt文件的编码处理过于绝对,部分txt文件可能为utf-8编码,建议添加异常捕获:elif 'txt' in file_name: try: df = pd.read_csv(io.StringIO(decoded.decode('utf-8')), delimiter='\t') except UnicodeDecodeError: df = pd.read_csv(io.StringIO(decoded.decode('utf-16')), delimiter='\t')- 全局变量
uploaded_df易引发状态混乱,建议改用dcc.Store组件存储上传数据。
- RadioItems初始值设为
文件权限/大小限制
若部署在服务器上,检查服务器的文件上传大小限制;本地环境则检查临时文件目录的读写权限。
修正后的核心回调逻辑示例
# 修改RadioItems初始值 dbc.Row([dcc.RadioItems(id='show_hide_table_button', options=['show_table', 'hide_table','show_plot'], value='hide_table')]), # 修正回调判断逻辑 def upload_data_file(contents, file_name, display): show_table = html.Div() show_plot = html.Div() # 替换全局变量为dcc.Store,此处先保留原有逻辑,后续建议重构 global uploaded_df if contents is not None: uploaded_df = parse_contents(contents, file_name) dropdown = uploaded_df.columns # ... 原有show_table、show_plot构建逻辑 ... # 补充全部分支判断 if display == 'show_table': return show_table elif display == 'hide_table': return None elif display == 'show_plot': return show_plot # 处理未匹配的情况 return None
内容的提问来源于stack exchange,提问作者Wayne Wu
相关产品推荐
相关产品推荐

