"Error loading dependencies" when trying to assess table data

Hello,

I am trying to do the following steps in a Dash program:
1. upload a csv file into a DataTable
2. select one column
3. upon pressing a button, create a new table with that column only
However, when I try to assess the initial table’s data in the button callback, the browser renders only the message “Error loading dependencies”.

The problem seems to be with these lines:

@app.callback(
    [Output('new-table', 'data'), Output('new-table', 'columns')],
    [Input('submit-button', 'n_clicks')],
    [State('data-table', 'data')]  # this line triggers "Error loading dependencies"
    )
def trigger_update(n_clicks, data):
    ...

Any help would be appreciated…
A complete example is attached below.

Regards,

jpp

# -*- coding: utf-8 -*-
import base64
import datetime
import io

import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
from dash.dependencies import Input, Output, State
import dash_table

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.config['suppress_callback_exceptions'] = True   # for avoiding error in "unknown" dynamic elements

app.layout = html.Div([
    html.Div(className="three columns", children=[
        html.Div([
            dcc.Upload(
                id='upload-data',
                children=html.Div([
                    'Drag and Drop or ',
                    html.A('Select Files')
                ]),
                style={
                    'width': '90%',
                    'height': '60px',
                    'lineHeight': '60px',
                    'borderWidth': '1px',
                    'borderStyle': 'dashed',
                    'borderRadius': '5px',
                    'textAlign': 'center',
                    'margin': '10px'
                },
                # Allow multiple files to be uploaded
                multiple=True
            ),
            html.Div(id='output-data-upload'),
        ]),
    ]),

    html.Div(className="two columns", children=[
        html.Label('Select column'),
        dcc.RadioItems(id='sel-col'),
        html.Hr(),
        html.Button(id='submit-button', n_clicks=0, children='Submit'),
    ]),

    html.Div(className="two columns", children=[
        html.Div(id='output-state', children='Initial value supplied here'),
        dash_table.DataTable(
            id='new-table',
            # editable=True
        ),

    ]),
], style={'columnCount': 1})


def parse_contents(contents, filename, date):
    content_type, content_string = contents.split(',')

    decoded = base64.b64decode(content_string)
    try:
        if 'csv' in filename:
            # Assume that the user uploaded a CSV file
            df = pd.read_csv(
                io.StringIO(decoded.decode('utf-8')))
        elif 'xls' in filename:
            # Assume that the user uploaded an excel file
            df = pd.read_excel(io.BytesIO(decoded))
    except Exception as e:
        print(e)
        return html.Div([
            'There was an error processing this file.'
        ])

    return html.Div([
        html.H5(filename),
        html.H6(datetime.datetime.fromtimestamp(date)),
        dash_table.DataTable(
            id='data-table',
            n_fixed_columns=100,
            n_fixed_rows=10,
            data=df.to_dict('records'),
            columns=[{'name': i, 'id': i} for i in df.columns],
            # editable=True
        ),

        html.Hr(),  # horizontal line
    ])


@app.callback(Output('output-data-upload', 'children'),
              [Input('upload-data', 'contents')],
              [State('upload-data', 'filename'),
               State('upload-data', 'last_modified')])
def update_output(list_of_contents, list_of_names, list_of_dates):
    if list_of_contents is not None:
        children = [
            parse_contents(c, n, d) for c, n, d in
            zip(list_of_contents, list_of_names, list_of_dates)]
        return children


@app.callback(
    Output('sel-col', 'options'),
    [Input('data-table', 'data'), Input('data-table', 'columns')])
def set_time_option(data, columns):
    return [{'label': i, 'value': i} for i in [c['name'] for c in columns]]


@app.callback(
    Output('output-state', 'children'),
    [Input('submit-button', 'n_clicks')],
    [State('sel-col', 'value')])
def update_output(n_clicks, col):
    return "{} clicks, sel-col is {}".format(n_clicks, col)


@app.callback(
    [Output('new-table', 'data'), Output('new-table', 'columns')],
    [Input('submit-button', 'n_clicks')],
    [State('data-table', 'data')]  # this line triggers "Error loading dependencies"
    )
def trigger_update(n_clicks, data):
    if n_clicks == 0:
        return [], []
    return [], []


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

I had the same error. I’m looking forward a reply., too.

You’re trying to listen to the id of a component that doesn’t exist when the app loads - it only exists when the function is run. And when you’re running the function, it returns many tables with the same ID. The data table components need to exist at app load. They can be hidden, but they have to exist.

If you remove app.config['suppress_callback_exceptions'] = True you can see the traceback for this.

Thanks for your feedback.

It is true that the table from which the flow should start does exist when the app loads – I am using the idiom found in the documentation for “upload component”:
https://dash.plot.ly/dash-core-components/upload

However, I don’t understand why the function “returns many tables with the same ID”. I’ve just copy-pasted the code in the documentation; I think parse_components should return only one table. Am I wrong?

For a static table, it would work (code below), but that does not solve my problem.

Regards,

jpp

# -*- coding: utf-8 -*-
import base64
import datetime
import io

import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
from dash.dependencies import Input, Output, State
import dash_table

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
# app.config['suppress_callback_exceptions'] = True   # for avoiding error in "unknown" dynamic elements

# df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/solar.csv')
df = pd.read_csv('solar.csv')

app.layout = html.Div([
    dash_table.DataTable(
        id='data-table',
        columns=[{"name": i, "id": i} for i in df.columns],
        data=df.to_dict('records'),
    ),

    html.Div(className="two columns", children=[
        html.Label('Select column'),
        dcc.RadioItems(id='sel-col'),
        html.Hr(),
        html.Button(id='submit-button', n_clicks=0, children='Submit'),
    ]),

    html.Div(className="two columns", children=[
        html.Div(id='output-state', children='Initial value supplied here'),
        dash_table.DataTable(
            id='new-table',
            # editable=True
        ),

    ]),

], style={'columnCount': 1})


@app.callback(
    Output('sel-col', 'options'),
    [Input('data-table', 'data'), Input('data-table', 'columns')])
def set_time_option(data, columns):
    return [{'label': i, 'value': i} for i in [c['name'] for c in columns]]


@app.callback(
    Output('output-state', 'children'),
    [Input('submit-button', 'n_clicks')],
    [State('sel-col', 'value')])
def update_output(n_clicks, col):
    return "{} clicks, sel-col is {}".format(n_clicks, col)


@app.callback(
    [Output('new-table', 'data'), Output('new-table', 'columns')],
    [Input('submit-button', 'n_clicks'), Input('sel-col', 'value')],
    [State('data-table', 'data'), State('data-table', 'columns')]  # this line triggers "Error loading dependencies"
    )
def trigger_update(n_clicks, col, data, columns):
    if n_clicks == 0:
        return [], []
    return data, [c for c in columns if c['name']==col]


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

Yes, parse_contents returns one datatable with id='data-table' each time it is called.

def parse_contents():
    ...
    return html.Div([
        html.H5(filename),
        html.H6(datetime.datetime.fromtimestamp(date)),
        dash_table.DataTable(
            id='data-table',
            n_fixed_columns=100,
            n_fixed_rows=10,
            data=df.to_dict('records'),
            columns=[{'name': i, 'id': i} for i in df.columns],
            # editable=True
        ),

        html.Hr(),  # horizontal line
    ])

But this returns a list of Divs, each containing a datatable with id='data-table'.

@app.callback(...)
def update_output(list_of_contents, list_of_names, list_of_dates):
    if list_of_contents is not None:
        children = [
            parse_contents(c, n, d) for c, n, d in
            zip(list_of_contents, list_of_names, list_of_dates)]
        return children

I tried to use your suggestion, but the problem subsists.
The code below is now producing one table (a dummy one before the user selects a file).
But if I try to add its state as an input to a button callback, I still have “Error loading dependencies”.
So, the problem must be elsewhere…
Regards,
jpp

# -*- coding: utf-8 -*-
import base64
import datetime
import io

import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
from dash.dependencies import Input, Output, State
import dash_table

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.config['suppress_callback_exceptions'] = True   # for avoiding error in "unknown" dynamic elements

app.layout = html.Div([
    html.Div(className="three columns", children=[
        html.Div([
            dcc.Upload(
                id='upload-data',
                children=html.Div([
                    'Drag and Drop or ',
                    html.A('Select a File')
                ]),
                style={
                    'width': '90%',
                    'height': '60px',
                    'lineHeight': '60px',
                    'borderWidth': '1px',
                    'borderStyle': 'dashed',
                    'borderRadius': '5px',
                    'textAlign': 'center',
                    'margin': '10px'
                },
                # Allow multiple files to be uploaded
                multiple=True
            ),
            html.Div(id='output-data-upload'),
        ]),
    ]),

    html.Div(className="two columns", children=[
        html.Label('Select column'),
        dcc.RadioItems(id='sel-col'),
        html.Hr(),
        html.Button(id='submit-button', n_clicks=0, children='Submit'),
    ]),

    html.Div(className="two columns", children=[
        html.Div(id='output-state', children='Initial value supplied here'),
        dash_table.DataTable(
            id='new-table',
            # editable=True
        ),

    ]),
], style={'columnCount': 1})




@app.callback(Output('output-data-upload', 'children'),
              [Input('upload-data', 'contents')],
              [State('upload-data', 'filename'),
               State('upload-data', 'last_modified')])
def parse_contents(contents, filename, date):
    if contents is not None:
        contents = contents[0]
        filename = filename[0]
        date = date[0]
        content_type, content_string = contents.split(',')

        decoded = base64.b64decode(content_string)
        try:
            if 'csv' in filename:
                # Assume that the user uploaded a CSV file
                df = pd.read_csv(
                    io.StringIO(decoded.decode('utf-8')))
            elif 'xls' in filename:
                # Assume that the user uploaded an excel file
                df = pd.read_excel(io.BytesIO(decoded))
        except Exception as e:
            print(e)
            return html.Div([
                'There was an error processing this file.'
            ])

        return html.Div([
            html.H5(filename),
            html.H6(datetime.datetime.fromtimestamp(date)),
            dash_table.DataTable(
                id='data-table',
                n_fixed_columns=100,
                n_fixed_rows=10,
                data=df.to_dict('records'),
                columns=[{'name': i, 'id': i} for i in df.columns],
                # editable=True
            ),
            html.Hr(),  # horizontal line
        ])
    # uncomment for having a dummy table in the begin
    else:
        return html.Div([
            html.H5("No file specified"),
            html.H6(datetime.datetime.fromtimestamp(0)),
            dash_table.DataTable(
                id='data-table',
                n_fixed_columns=100,
                n_fixed_rows=10,
                data=[{'column-1': 4.5, 'column-2': 'montreal', 'column-3': 'canada'}, {'column-1': 8, 'column-2': 'boston', 'column-3': 'america'}],
                columns=[{'name': i, 'id': i} for i in ["C1", "C2", "C3"]],
                # editable=True
            ),
            html.Hr(),  # horizontal line
        ])


@app.callback(
    Output('sel-col', 'options'),
    [Input('data-table', 'data'), Input('data-table', 'columns')])
def set_time_option(data, columns):
    return [{'label': i, 'value': i} for i in [c['name'] for c in columns]]


@app.callback(
    Output('output-state', 'children'),
    [Input('submit-button', 'n_clicks')],
    [State('sel-col', 'value'), State('upload-data', 'last_modified')])
def update_output(n_clicks, col, filename):
    return "{} clicks, sel-col is {}, sel-file is {}".format(n_clicks, col, filename)


@app.callback(
    [Output('new-table', 'data'), Output('new-table', 'columns')],
    [Input('submit-button', 'n_clicks')],
    [State('data-table', 'data')]  # this line triggers "Error loading dependencies"
    )
def trigger_update(n_clicks):
    if n_clicks == 0:
        return [], []
    return [], []


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

I’ve opened an issue for this: