Many Updates On One Page Load. Dash App

Im trying implement “Updates on Page Load” as you document says at Live Updates | Dash for Python Documentation | Plotly
Trying this python code :

import dash
import dash_html_components as html
import datetime

def serve_layout():
    d = str(datetime.datetime.now())
    print ""
    print "SELECT * FROM ... #This SQL Query should run once! "
    print "This should run ONCE every GET of browser!! ",d, " ..."
    print ""
    return html.H1('The time is: ' + d)

app = dash.Dash(__name__)
app.layout = serve_layout

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

I got this on line command console:

$ python b01.py

SELECT * FROM … #This SQL Query should run once!
This should run ONCE every GET of browser!! 2017-07-01 22:07:58.632625 …

SELECT * FROM … #This SQL Query should run once!
This should run ONCE every GET of browser!! 2017-07-01 22:07:58.634538 …

SELECT * FROM … #This SQL Query should run once!
This should run ONCE every GET of browser!! 2017-07-01 22:08:07.365613 …

SELECT * FROM … #This SQL Query should run once!
This should run ONCE every GET of browser!! 2017-07-01 22:08:07.367369 …

  • Debugger is active!
  • Debugger PIN: 289-950-892

SELECT * FROM … #This SQL Query should run once!
This should run ONCE every GET of browser!! 2017-07-01 22:08:48.421873 …

SELECT * FROM … #This SQL Query should run once!
This should run ONCE every GET of browser!! 2017-07-01 22:08:48.422106 …

SELECT * FROM … #This SQL Query should run once!
This should run ONCE every GET of browser!! 2017-07-01 22:08:48.422447 …

SELECT * FROM … #This SQL Query should run once!
This should run ONCE every GET of browser!! 2017-07-01 22:08:48.422617 …

127.0.0.1 - - [01/Jul/2017 22:08:48] “GET / HTTP/1.1” 200 -
127.0.0.1 - - [01/Jul/2017 22:08:48] “GET /_dash-dependencies HTTP/1.1” 200 -

SELECT * FROM … #This SQL Query should run once!
This should run ONCE every GET of browser!! 2017-07-01 22:08:48.790658 …

127.0.0.1 - - [01/Jul/2017 22:08:48] “GET /_dash-layout HTTP/1.1” 200 -
127.0.0.1 - - [01/Jul/2017 22:08:48] “GET /_dash-routes HTTP/1.1” 200 -

How to solve this? Thanks!

Nice catch @expresiondigitalnet! Indeed, it looks like it is run twice on start and 7 times on serving the page.

This should probably be considered a bug. Until this is fixed, you could add caching so that a new value is only computed every 5 minutes or every hour or every day. There is a tutorial on caching here: https://plot.ly/dash/performance

I’m having the same issue, like @expresiondigitalnet I need to run a DB query on page load.

The current behavior is that when starting the app, my query executes 4 times, and then 7 more when the page is loaded, and 5 more each time the page is refreshed. This seems pretty egregious (and in fact undermines my application), is there a work-around for this?

1 Like

I’m having a similar issue when a callback has ‘N’ inputs. It seems that the callback function is called ‘N’ times on page load.
This is a bit cumbersome when the callback is slow. The following example reproduces this issue:

import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
from dash.dependencies import Input, Output
import numpy as np
import time

app = dash.Dash()


def make_plot(value1, value2, value3, value4):
    x = np.random.randn(value1) + value3
    y = np.random.randn(value2) + value4
    trace = go.Scatter(x=x, y=y, mode='markers')
    return {'data': [trace]}

app.layout = html.Div([
    dcc.Graph(id='1'),
    dcc.Slider(id='2', min=0, max=100, value=50, step=1),
    dcc.Slider(id='3', min=0, max=100, value=50, step=1),
    dcc.Slider(id='4', min=0, max=100, value=50, step=1),
    dcc.Slider(id='5', min=0, max=100, value=50, step=1)
])


@app.callback(
    Output('1', 'figure'),
    [Input('2', 'value'),
     Input('3', 'value'),
     Input('4', 'value'),
     Input('5', 'value')])
def test(value1, value2, value3, value4):
    time.sleep(2)
    return make_plot(value1, value2, value3, value4)

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

Would it possible to fix this behaviour? Cheers!

Have had the same experiences. Wish I’d mentioned it; been debugging for two weeks! @chriddyp - want me to file an issue on Git?

1 Like

That would be great. It sounds like a lot of users are seeing this issue, so it’s something I should prioritize. I’ll see if I can fit it in next week.

1 Like

Tracked here https://github.com/plotly/dash/issues/116

2 Likes

Anyone made any progress with this, or have a workaround that may be viable?

1 Like

Same issue even in simple user guide’s example :
import dash
import dash_html_components as html
import datetime

app=dash.Dash()

def serve_layout():
print(“Started”)
return html.H1('The time is: ’ + str(datetime.datetime.now()))

app.layout = serve_layout

if name == ‘main’:
app.run_server()

image

Update: number of times this code prints “Started” depends of web browser. 5 times for google chrome 3 times for ie and firefox =|

I’ve read some time ago that multiple roundtrips were caused by a python websocket implementation. I don’t remember the source nor did I nail it down to this problem for Dash. Pardon my ignorance. That’d be just a place to start looking at.

I haven’t worked on this yet but I"ll look into it this morning.

Dash doesn’t actually use websockets, just straight HTTP requests with flask.

1 Like

Fixed in https://github.com/plotly/dash/pull/128, the fix will be available in the v0.18.1 release.

2 Likes

Holy crap that was quick @chriddyp. On your first coffee?

Can’t wait to try!

2 Likes

v0.18.1 has been published. Upgrade with pip install dash==0.18.1. Here’s the example app that I’m testing with:

import dash
from dash.dependencies import Input, Output
import dash_html_components as html
import dash_core_components as dcc

app = dash.Dash()

print('App start')


def serve_layout():
    print('Calling layout')
    return html.Div([
        html.Div(id='output-1'),
        html.Div(id='output-2'),
        dcc.Dropdown(
            id='input',
            options=[{'label': i, 'value': i} for i in ['a', 'b']]
        )
    ])


app.layout = serve_layout


@app.callback(Output('output-1', 'children'), [Input('input', 'value')])
def update_outout(value):
    return 'You have selected {}'.format(value)


@app.callback(Output('output-2', 'children'), [Input('input', 'value')])
def update_outout(value):
    return 'You have selected {}'.format(value)


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

Just barely :wink:

3 Likes

Still seeing multiple calls in a special case? input 1 effects output 1, then input 1 and output 1 are used as inputs to another function. See below:

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import json
#Define Dash App
app=dash.Dash()

def app_layout():
return(
        html.Div([
            html.Div([
                    dcc.Dropdown(id='options',
                                 options=[{'label':'1', 'value':1},
                                          {'label':'2', 'value':2},
                                          {'label':'3', 'value':3}],
                                 value=1),
                    dcc.Dropdown(id='options2',
                                 options=[{'label':'1', 'value':1},
                                          {'label':'2', 'value':2},
                                          {'label':'3', 'value':3}],
                                 value=2),
                    dcc.Dropdown(id='options3',
                                 options=[{'label':'1', 'value':1},
                                          {'label':'2', 'value':2},
                                          {'label':'3', 'value':3}],
                                 value=3)
                    ]),
            html.Div([
                    dcc.Markdown("""
                                 **Dropdowns**
                                 """.replace('   ', '')),
                    html.Pre(id='click-data', style={'border': 'thin lightgrey solid'})
                        ])
                ])
    )
                #style={'backgroundColor': '#F9F9F9', 'width':'49%', 'margin':50}),

app.layout=app_layout

@app.callback(
    Output('options2', 'value'),
    [Input('options','value')])                 
def update_options2(one):
    print 'UPDATING OPTIONS2'                  
    return one

@app.callback(
    Output('options3', 'value'),
    [Input('options','value')])                 
def update_options3(one):
    print 'UPDATING OPTIONS3'                  
    return one
        
@app.callback(
    Output('click-data', 'children'),
    [Input('options','value'),
     Input('options2','value'),
     Input('options3','value')])                 
def display_click_data(one, two, three):  
    print 'OUTPUT OPTIONS'                
    return json.dumps(str(one)+str(two)+str(three))


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

new version:

@emunson - I believe that is a separate issue (Specifying dependency tree traversal). Coincidently, I’m working on that issue today as well.

I am having a same issue, My dashboard gets data from database using ODBC. When a page loads I can see it fires a same query 4 times to the database and some queries are getting executed 7 times. I only want it run once and get the data in data table. My current version of Dash is ‘1.16.3’.