0

I'm building a dashboard in Dash, where I want to visualie a dataset that I load at the start of the dashboard. As this dataset is to be used by all methods in the dashboard, I keep it in a singleton class.

The issue is though that the data is loaded twice when I start the dashboard ("generated" is shown twice in the console when I start the dashboard). Here is a MWE showing the problem:

app.py

from dash import Dash, dcc, html

from callbacks import get_callbacks
from data import MyData

app = Dash(__name__, suppress_callback_exceptions=True)

get_callbacks(app) #load all callbacks    
m = MyData() #load data at start of the dashboard -- somehow, this happens twice?

if __name__ == '__main__':
    app.layout = html.Div([dcc.Location(id="url")])
    app.run_server(debug=True)

data.py

import pandas as pd


def generate_df():
    print("generated")
    return pd.DataFrame({'a':[1,2,3]})

class MyData:
    def __new__(cls):
        if not hasattr(cls, 'instance'):
            cls.instance = super(MyData, cls).__new__(cls)
        return cls.instance
        
    def __init__(self):
        self.df = generate_df()

callbacks.py

def get_callbacks(app):
    pass

Where does this additional load of data happen?

TylerD
  • 361
  • 1
  • 9
  • Your `__init__` function gets called twice, once from your `super(MyData, cls).__new__(cls)` call, and then once again because `__init__` is always executed on object instanciation. Maybe [this thread](https://stackoverflow.com/questions/8106900/new-and-init-in-python) helps clear things up. I would recommend to only use one, personally i have never needed `__new__`. As far as i see, you could simply add `self.instance = self` to your `__init__`, remove the entire `__new__` function block and achieve the same thing. – mnikley Jan 18 '23 at 08:39
  • @mnikley Thanks. I tried commenting out `def __new__(....`, but the issue persists so I think there is another issue as well besides the super-call – TylerD Jan 18 '23 at 09:04
  • 1
    you are right - my explanation had nothing to do with your issue. Seems like when you use `app.run_server(debug=True)` it runs the entire script `app.py` again, i think due to the debug functionality of dash. Add `use_reloader=False` to your `app.run_server` to prevent this: `app.run_server(debug=True, use_reloader=False)` (of course, then you lose the auto-reloading functionality of dash / Flask) – mnikley Jan 18 '23 at 09:33

0 Answers0