Dash callback in a separate file

Hey everyone,

I’ve been learning Dash over the past few days and am going through the tutorial. As I’ve done more and more callbacks, I realized app.py file was getting way too big. I’m afraid that in a real-case scenario, having the callbacks within app.py file might be a mess, so I’d like to have the following architecture:
app.py that contains the main app and its layout
callbacks1.py that contains some callback functions
callbacks2.py same thing

I’ve ALMOST managed to make it work. Here is my code:
app3.py

# -*- coding: utf-8 -*-

################################################################################
###
### IMPORTS
###
################################################################################
import os
import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd




################################################################################
###
### SETUP
###
################################################################################
path = os.path.dirname(os.path.abspath(__file__))
os.chdir(path)
app = dash.Dash(__name__)
df3 = pd.read_csv('data/test_data_3.csv', sep='|')



################################################################################
###
### LAYOUT
###
################################################################################
app.layout = html.Div([
    html.Div([
        dcc.Graph(id='graph-with-slider'),
        dcc.Slider(
            id='year-slider',
            min=df3['year'].min(),
            max=df3['year'].max(),
            value=df3['year'].max(), # Base value
            marks={str(year): str(year) for year in df3['year'].unique()},
        ),
    ]),
])



################################################################################
###
### CALLBACKS
###
################################################################################
import cbs3



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

cbs3.py

import plotly.graph_objs as go
import dash.dependencies as dd
from app3 import app, df3

@app.callback(
    dd.Output('graph-with-slider', 'figure'),
    [dd.Input('year-slider', 'value')]
)
def update_with_slider(selected_year):
    """ Update the figure property of our graph based on the slider value, everytime it is modified """
    filtered_df = df3[df3.year == selected_year]
    traces = []
    for i in filtered_df.continent.unique():
        df_by_continent = filtered_df[filtered_df.continent == i]
        traces.append(go.Scatter(
            x=df_by_continent.gdpPercap,
            y=df_by_continent.lifeExp,
            text=df_by_continent.country,
            mode='markers',
            opacity=0.7,
            marker={
                'size':15,
                'line': {'width':0.5, 'color': 'white'}
            },
            name=i,
        ))
    # We return a dict that basically is the property for the dcc.Graph() element.
    return {
        'data': traces,
        'layout': go.Layout(
            xaxis={'type': 'log', 'title': 'GPD Per Capita',},
            yaxis={'title': 'Life Expectancy', 'range': [20, 90]},
            margin={'l': 40, 'b': 40, 't': 10, 'r': 10},
            legend={'x': 0, 'y': 1},
            hovermode='closest',
        ),
    }

The weird thing is that: if I change “import cbs3” into “from cbs3 import *”, it works. If I leave "import cbs3’, it doesn’t work. I’d like to understand why and be able to fix it, as I know using “import *” is not a good idea.

Any help would be greatly appreciated.
Thanks

2 Likes