Black Lives Matter. Please consider donating to Black Girls Code today.

Unrelated call backs preventing other call backs from running

Hello.

I was trying to figure out why my combination of two piece of code I found online wasn’t working. To test this I decided to run them both at the same time.

I noticed though that it seems that my one call back is preventing the other from running. Once the second callback is run the first callback begins to work.

The thing is they have nothing to do with each other. I even made sure that no local variables were being shared as well as the order in which the callbacks appeared in the code.

The code is as follows (combination of https://github.com/plotly/dash-recipes/blob/master/upload-data-to-table.py and https://dash.plot.ly/getting-started)

import dash_html_components as html
import dash_core_components as dcc
import dash

import plotly
import dash_table_experiments as dte
from dash.dependencies import Input, Output, State

import pandas as pd
import numpy as np

import json
import datetime
import operator
import os

import base64
import io

df1 = pd.read_csv(
    'https://gist.githubusercontent.com/chriddyp/'
    'c78bf172206ce24f77d6363a2d754b59/raw/'
    'c353e8ef842413cae56ae3920b8fd78468aa4cb2/'
    'usa-agricultural-exports-2011.csv')

def generate_table(dataframe, max_rows=10):
    return html.Table(
        # Header
        [html.Tr([html.Th(col) for col in dataframe.columns])] +

        # Body
        [html.Tr([
            html.Td(dataframe.iloc[i][col]) for col in dataframe.columns
        ]) for i in range(min(len(dataframe), max_rows))]
    )

def parse_contents(contents, filename):
    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 None

    return df

app = dash.Dash()

app.layout = html.Div(children=[


    html.H5("Upload Files"),
    dcc.Upload(
        id='upload-data',
        children=html.Div([
            'Drag and Drop or ',
            html.A('Select Files')
        ]),
        multiple=False),
    html.Br(),
    html.H5("Updated Table"),
    html.Div(dte.DataTable(rows=[{}], id='table2')),

    html.H4(children='US Agriculture Exports (2011)'),
    html.Button(
        id='Make_Graph1',
        n_clicks = 0,
        children='Launch'
    ),
    html.Div(
        id = "BLARG"
    ),

])

@app.callback(Output('table2', 'rows'),
              [Input('upload-data', 'contents'),
               Input('upload-data', 'filename')])
def update_output(contents, filename):
    if contents is not None:
        df2 = parse_contents(contents, filename)
        if df2 is not None:
            return df2.to_dict('records')
        else:
            return [{}]
    else:
        return [{}]

@app.callback(Output('BLARG', 'children'),
        [Input('Make_Graph1', 'n_clicks')])
def Make_Table(Click):
    if Click <1:
        return [{}]
    else:
        return generate_table(df1)

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

If the button is clicked then Make_Table launches correctly. If then a file is uploaded then update_output is generated correctly.

However if a file is uploaded then update_output fails to launch. If however one then runs Make_Table then update_output starts to work.

The two call backs share nothing as far as I can tell so I see no reason why there is a conflict.

I was wondering if this is a bug or if I’m missing something.

Any help or work arounds would be much appreciated.

When you run dash with app.run_server(debug=True), only a single python process is running, so it can only handle one callback at a time. Run the app with gunicorn or waitress in order to run with multiple processes

This will make two callbacks when you upload, you should change one of the input to a state:

@app.callback(Output('table2', 'rows'),
              [Input('upload-data', 'contents')],
              [State('upload-data', 'filename')])

Thank you for taking the time to respond.

However if I replace the code as you have said it still has the same problem as previously described.

I’m sorry if I’m being a bit thick but I don’t see why 2 call backs that are in no way related apart from appearing on the same page should interfere with each other. I could understand if the one call back was related to the other but as far as I can tell the 2 call backs have nothing in common.

Thank you for you reply.

When I launch the sheet it should check if Click is > 1 and whether df != None. Since neither of these are true my two callbacks return nothing. When I then load a dataframe the only callback activated by that should be the one relating to dataframes.

Are you saying that the other callback is trying to run even though it hasn’t been called on?

Many thanks for all your hard work.