Black Lives Matter. Please consider donating to Black Girls Code today.
Dash HoloViews is now available! Check out the docs.

Multiple callbacks executed by a single Input change

I have a Plotly application with a DatePickerRange input and a Dropdown input which power a set of dashboards.

Whenever an input is modified, I have a callback which registers this change and refreshes the data that powers the dashboard.

@app.callback(
    dash.dependencies.Output('time-series-figure', 'figure'),
    [dash.dependencies.Input('my-date-picker-range', 'start_date'),
    dash.dependencies.Input('my-date-picker-range', 'end_date'),
    dash.dependencies.Input('extruder-choice', 'value')]
        )
def update_daterange(startdate, enddate, extruder):
      date_range = [startdate, enddate]
      return self.refresh(date_range, extruder)

I noticed that this was taking more time than I expected. After placing a pdb.set_trace() within the function:

def update_daterange(startdate, enddate, extruder):
    date_range = [startdate, enddate]
    pdb.set_trace()  
    return self.refresh(date_range, extruder)

And inspecting my console:

127.0.0.1 - - [04/Jun/2018 12:03:04] "POST /_dash-update-component HTTP/1.1" 200 -
(Pdb) c
127.0.0.1 - - [04/Jun/2018 12:03:07] "POST /_dash-update-component HTTP/1.1" 200 -
(Pdb) c
127.0.0.1 - - [04/Jun/2018 12:03:09] "POST /_dash-update-component HTTP/1.1" 200 -
(Pdb) c
127.0.0.1 - - [04/Jun/2018 12:03:11] "POST /_dash-update-component HTTP/1.1" 200 -
(Pdb) c

I noticed that this callback was being executed exactly 4 times. Since I am running the server in debug mode, as the following code specifies, I am anticipating that only one request should be made.

dl = DataLoader(connection_config=connection_config)
dl.connect()

db = Dashboard(dl)
db.configure()

if __name__ == '__main__':
    db.app.run_server(debug=True, port=8051)

This is because of the default options on run_server

results in the default Flask options to be used:

which in turn call the Werkzeug function run_simple,

which has the default number of processes equal to 1.

Why is the callback executed 4 times?

Thanks for your help!

Best,
Will

My guess is:

  • Once on page load to initialize
  • Another time when one of the inputs change
  • All of that times 2 because of a recent dash-renderer bug that got fixed: https://github.com/plotly/dash-renderer/pull/54 and released (dash-renderer==0.13.0)

Hi chriddyp,

I have now upgraded my version of dash-renderer to be 0.13.0, but strangely enough, continue to register 4 executions of the callback. This occurs after the page has loaded, and so only when one of the inputs change.

I am reasonably confident that this is what is happening, but I am continuing to dig. Any suggestions/potential directions to follow would be greatly appreciated!

Thanks for your help as always,
Will

Thanks for checking @willgdjones! This could be a bug. Could you create a really small, reproducable example that demonstrates this issue? The smaller/simpler the better.

Hi @chriddyp, here is a gist of a minimum viable example.

Upon modifying the DateRangePicker, there are in fact 3 executions of the callback. When I modify the Dropdown component, though, there is a single callback.

Let me know if you can reproduce this!

Versions:
dash-html-components==0.9.0

plotly==2.5.1
dash==0.21.0
numpy==1.14.1
pandas==0.23.0
dash-core-components==0.21.0
dash-renderer==0.13.0

Thanks @willgdjones! checking this out now.

Looks like a bug in the DatePickerRange component. Should be an easy fix. I’ve created an issue here: https://github.com/plotly/dash-core-components/issues/209

1 Like

I do get a similar bug when using callbacks that have multiple inputs, as in:

dynamically_generated_function = self._createCallback()
self._app.callback(
    Output(elem, 'style'),
    [Input(dropdown, 'value'),
    Input(mainInput, 'value'),
    Input(secInput, 'value')],
    [State(mainInput, 'value'),
    State(secInput, 'value')]
)(dynamically_generated_function)

I print out stuff in the callback function to see how many times it executes and it consistently does so 3 times even though I only change the value in one input, single digit… Is that supposed to happen?

EDIT: Also all my dash libraries are up-to-date.

That shouldn’t happen. Can you share a small, reproducable example?

I’ll try to, might have to write one specifically, as the app is huge.

Tried to reproduce, fixed instead it seems. :cry:

3 Likes