Dash server not updating through examples


#1

Working through the Dash examples. When I load one such as the “Core Components” example. I copy it into my python editor (Canopy Enthought), run, and will see it in both Chrome and Firefox. I try to then load the “Update Graphs on Hover” example and run it. Even though the debug indicates “Running on http://127.0.0.1:8050”. Neither Firefox or Chrome will reload with the new script. Using Windows Pro 7.


#2

A reproducible example would help a lot, with very clear instructions on the actual code you used (with links so others can try), what steps you’re doing, what you expected, and what actually happened. I’m guessing, for example, that you are wondering why it didn’t reload on the fly when you pasted it into your editor?

I’m just going by when you say you “load one” and then say that you copied it into your editor and chose run. I don’t have this editor, but I did an example like so:

  • created a file, test-app.py, pasted in this components example, saved file
  • opened a terminal and went to the directory, then did python test-app.py
  • I get this output:
 * Running on http://127.0.0.1:8050/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 123-456-789
  • I then deleted the contents of my file, pasting in the second example from here (multi-colored scatter plot)
  • upon saving, I get this in the terminal (still running):
* Detected change in '/path/to/dash-reload-test/test-app.py', reloading
 * Restarting with stat
  • when I Ctrl-R on the screen, the component example is gone and I have the scatter plot

Hopefully that helps a little bit? Without more details, I’m guessing, but the only things that come to mind are:

  • as far as I know, you will need to reload the page to see the new app. It won’t reload itself (at least without doing something to make that happen in the code)
  • note that the second example does not feature the debug=T arg to app.run_server(). This is what provides the instant restart of the server upon a file change. When I Ctrl-c to kill my running server, then restart with python test-app.py, I get the scatter plot again (current contents of my file). When I undid my delete/paste to get back to the components example and saved, I did not get the terminal output about Restarting with stat because the first app launched didn’t enable the debugger. Refreshing the page still shows the scatter plot, even though the file now contains the component example. In this case dash is not “watching” and you’ll have to kill the process and restart to show changes.

Hope something in there is useful!


#3

Another guess: You might need to hit “Stop” on the first script before you hit “Run” on the second script.


#4

Thanks. So, what I was doing was saving a file ‘dash_dropdown.py’:

# -*- coding: utf-8 -*-
import dash
import dash_html_components as html
import dash_core_components as dcc

app = dash.Dash()

app.layout = html.Div([
html.Label('Dropdown'),
dcc.Dropdown(
    options=[
        {'label': 'New York City', 'value': 'NYC'},
        {'label': u'Montréal', 'value': 'MTL'},
        {'label': 'San Francisco', 'value': 'SF'}
    ],
    value='MTL'
),

html.Label('Multi-Select Dropdown'),
dcc.Dropdown(
    options=[
        {'label': 'New York City', 'value': 'NYC'},
        {'label': u'Montréal', 'value': 'MTL'},
        {'label': 'San Francisco', 'value': 'SF'}
    ],
    value=['MTL', 'SF'],
    multi=True
),

html.Label('Radio Items'),
dcc.RadioItems(
    options=[
        {'label': 'New York City', 'value': 'NYC'},
        {'label': u'Montréal', 'value': 'MTL'},
        {'label': 'San Francisco', 'value': 'SF'}
    ],
    value='MTL'
),

html.Label('Checkboxes'),
dcc.Checklist(
    options=[
        {'label': 'New York City', 'value': 'NYC'},
        {'label': u'Montréal', 'value': 'MTL'},
        {'label': 'San Francisco', 'value': 'SF'}
    ],
    values=['MTL', 'SF']
),

html.Label('Text Input'),
dcc.Input(value='MTL', type='text'),

html.Label('Slider'),
dcc.Slider(
    min=0,
    max=9,
    marks={i: 'Label {}'.format(i) if i == 1 else str(i) for i in range(1, 6)},
    value=5,
),
], style={'columnCount': 2})

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

I would save this file and run it. My browser would show it as advertised. I would then save a seperate file named ‘dash_update graph.py’:

# -*- coding: utf-8 -*-
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
import pandas as pd

app = dash.Dash()

df = pd.read_csv(
'https://gist.githubusercontent.com/chriddyp/cb5392c35661370d95f300086accea51/raw/8e0768211f6b747c0db42a9ce9a0937dafcbd8b2/indicators.csv')

available_indicators = df['Indicator Name'].unique()

app.layout = html.Div([
html.Div([

    html.Div([
        dcc.Dropdown(
            id='crossfilter-xaxis-column',
            options=[{'label': i, 'value': i} for i in available_indicators],
            value='Fertility rate, total (births per woman)'
        ),
        dcc.RadioItems(
            id='crossfilter-xaxis-type',
            options=[{'label': i, 'value': i} for i in ['Linear', 'Log']],
            value='Linear',
            labelStyle={'display': 'inline-block'}
        )
    ],
    style={'width': '49%', 'display': 'inline-block'}),

    html.Div([
        dcc.Dropdown(
            id='crossfilter-yaxis-column',
            options=[{'label': i, 'value': i} for i in available_indicators],
            value='Life expectancy at birth, total (years)'
        ),
        dcc.RadioItems(
            id='crossfilter-yaxis-type',
            options=[{'label': i, 'value': i} for i in ['Linear', 'Log']],
            value='Linear',
            labelStyle={'display': 'inline-block'}
        )
    ], style={'width': '49%', 'float': 'right', 'display': 'inline-block'})
], style={
    'borderBottom': 'thin lightgrey solid',
    'backgroundColor': 'rgb(250, 250, 250)',
    'padding': '10px 5px'
}),

html.Div([
    dcc.Graph(
        id='crossfilter-indicator-scatter',
        hoverData={'points': [{'customdata': 'Japan'}]}
    )
], style={'width': '49%', 'display': 'inline-block', 'padding': '0 20'}),
html.Div([
    dcc.Graph(id='x-time-series'),
    dcc.Graph(id='y-time-series'),
], style={'display': 'inline-block', 'width': '49%'}),

html.Div(dcc.Slider(
    id='crossfilter-year--slider',
    min=df['Year'].min(),
    max=df['Year'].max(),
    value=df['Year'].max(),
    step=None,
    marks={str(year): str(year) for year in df['Year'].unique()}
), style={'width': '49%', 'padding': '0px 20px 20px 20px'})
])

@app.callback(
    dash.dependencies.Output('crossfilter-indicator-scatter', 'figure'),
   [dash.dependencies.Input('crossfilter-xaxis-column', 'value'),
    dash.dependencies.Input('crossfilter-yaxis-column', 'value'),
    dash.dependencies.Input('crossfilter-xaxis-type', 'value'),
    dash.dependencies.Input('crossfilter-yaxis-type', 'value'),
    dash.dependencies.Input('crossfilter-year--slider', 'value')])
def update_graph(xaxis_column_name, yaxis_column_name,
             xaxis_type, yaxis_type,
             year_value):
dff = df[df['Year'] == year_value]

return {
    'data': [go.Scatter(
        x=dff[dff['Indicator Name'] == xaxis_column_name]['Value'],
        y=dff[dff['Indicator Name'] == yaxis_column_name]['Value'],
        text=dff[dff['Indicator Name'] == yaxis_column_name]['Country Name'],
        customdata=dff[dff['Indicator Name'] == yaxis_column_name]['Country Name'],
        mode='markers',
        marker={
            'size': 15,
            'opacity': 0.5,
            'line': {'width': 0.5, 'color': 'white'}
        }
    )],
    'layout': go.Layout(
        xaxis={
            'title': xaxis_column_name,
            'type': 'linear' if xaxis_type == 'Linear' else 'log'
        },
        yaxis={
            'title': yaxis_column_name,
            'type': 'linear' if yaxis_type == 'Linear' else 'log'
        },
        margin={'l': 40, 'b': 30, 't': 10, 'r': 0},
        height=450,
        hovermode='closest'
    )
}

def create_time_series(dff, axis_type, title):
return {
    'data': [go.Scatter(
        x=dff['Year'],
        y=dff['Value'],
        mode='lines+markers'
    )],
    'layout': {
        'height': 225,
        'margin': {'l': 20, 'b': 30, 'r': 10, 't': 10},
        'annotations': [{
            'x': 0, 'y': 0.85, 'xanchor': 'left', 'yanchor': 'bottom',
            'xref': 'paper', 'yref': 'paper', 'showarrow': False,
            'align': 'left', 'bgcolor': 'rgba(255, 255, 255, 0.5)',
            'text': title
        }],
        'yaxis': {'type': 'linear' if axis_type == 'Linear' else 'log'},
        'xaxis': {'showgrid': False}
    }
}

@app.callback(
     dash.dependencies.Output('x-time-series', 'figure'),
     [dash.dependencies.Input('crossfilter-indicator-scatter', 'hoverData'),
    dash.dependencies.Input('crossfilter-xaxis-column', 'value'),
    dash.dependencies.Input('crossfilter-xaxis-type', 'value')])
    def update_y_timeseries(hoverData, xaxis_column_name, axis_type):
 country_name = hoverData['points'][0]['customdata']
dff = df[df['Country Name'] == country_name]
dff = dff[dff['Indicator Name'] == xaxis_column_name]
title = '<b>{}</b><br>{}'.format(country_name, xaxis_column_name)
return create_time_series(dff, axis_type, title)

@app.callback(
   dash.dependencies.Output('y-time-series', 'figure'),
  [dash.dependencies.Input('crossfilter-indicator-scatter', 'hoverData'),
  dash.dependencies.Input('crossfilter-yaxis-column', 'value'),
 dash.dependencies.Input('crossfilter-yaxis-type', 'value')])
def update_x_timeseries(hoverData, yaxis_column_name, axis_type):
dff = df[df['Country Name'] == hoverData['points'][0]['customdata']]
dff = dff[dff['Indicator Name'] == yaxis_column_name]
return create_time_series(dff, axis_type, yaxis_column_name)

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

When I would save this second file, and run it from IPython, it would indicate that it was running at 127.0.0:8050, but not matter what I did, my browser wouldn’t pick it up. I would refresh, delete history, delete web cache. Nothing would update the web browser portion.

You did give me an idea though, I copied and pasted the code from the update graph file, and pasted in over the dropdown file. When I ran the dropdown file it like that, it ran fine and updated with whatever code I entered. So once I run a certain file, that is the file I am running I guess. Also, this wouldn’t allow me to use Ctl - C to stop it. I had to restart the kernel every time I wanted to make updates. I don’t think this will do what I am wanting to for this project. I may try and pick this up again later to see if I can make it more robust.

Thanks for the assistance.


#5

Hmmm. Based on your description, is it fair to say:

  • you create dash_dropdown.py, then do python ./dash_dropdown.py, and leave it running
  • you create dash_update_graph.py and then do python ./dash_update_graph.py

?

I’d expect that shouldn’t work, as they can’t both run at the same address (127.0.0.1:8050 is already in use from the first file launched)? I just tried this and get OSError: [Errno 98] Address already in use.

Maybe try outside of Ipython? Just manually run it with python file.py from a terminal/command prompt and you should be able to kill with Ctrl-C. This will remove a layer of potential complexity/pitfalls.

Lastly, maybe someone with more experience can help you with the true aim you’re going for… Like when you say “I don’t think this will do what I am wanting,” what is your project need that you need either two concurrent dash instances running, or reload-on-the-fly, or pasting over a file with another? I would guess eventually you’d just launch/deploy these and not touch them once running.

If you just need two different servers running, see this github issue. I just made one of my files feature the port option:

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

I can now run both at the same time, one at 127.0.0.1:8000 and the other at 127.0.0.1:8050 (default).


#6

No, I am not needing to run two different servers at the same time. I would try to stop the dropdown file BEFORE trying to run the update_graph file. I could never get it to shutdown as advertised. Always had to restart the kernel before I could run a different file, and then the server wouldn’t update. Am I missing a crucial bit of information here? If I stop the program and/or restart the kernel, does that effectively shutdown the server?

I tried running it from the command line prompt and received “lookuperror no codec search functions registered”. I confirmed that Python is added to my ‘Path’ and was able to start an IPython session from the command line.

What I am trying to do, is I have a python script that analyzes data from a couple of different files and then displays several graphs about that information. I am currently using a Jupyter Notebook, pandas, and plot.ly with some file dialog boxes courtesy of PyQt4.

I am needing to push this to other users that may not be as ‘tech nerd’ as I am, so I am trying to make it a little more robust and polished, and easy to use. I was hoping Dash would do this.

Thank you for the time in trying to help.


#7

Ah, that’s helpful. I’m going to guess it’s some interaction between dash and jupyter/ipython, but I don’t have much experience. I just tried to replicate like so:

  • run jupyter lab from command line
  • paste in your dash_dropdown.py code from above
  • click run button
 * Running on http://127.0.0.1:8050/ (Press CTRL+C to quit)
 * Restarting with stat
An exception has occurred, use %tb to see the full traceback.

SystemExit: 1
~/.local/lib/python3.6/site-packages/IPython/core/interactiveshell.py:2918: UserWarning:

To exit: use 'exit', 'quit', or Ctrl-D.

So I’m not even able to replicate at the moment. If this is an issue with dash and jupyter interaction, I found some posts that might be helpful (also indicates special things are required, which makes me think this is, indeed, why you’re having troubles):

Wow! So, that last link is a github issue and I just tried @chriddyp’s suggestion to just run with debug=False and it seems to work! Check it out. I’ve got two dash apps pasted, and the play/stop buttons work as expected, provided I reload after starting the second. The sequence is play, show it’s working, go back and stop, refresh to show it’s dead, start the second, reload to show it’s changed.


DASH does not implement the changes I make to the code