How does Dash import system work?

I have the most basic app that uses pages:

app.py

from dash import Dash

app = Dash(__name__, use_pages=True)

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

Then I have some expensive MongoDB connection that I initialize in a separate file:

mongo_client.py

import os
from my_lib import AugmentedMongoClient

mngdb = AugmentedMongoClient(
    seeds=os.environ['HOSTS'],
    replicaset=os.environ['RS'],
    username=os.environ['USER'],
    password=os.environ['PASS']
)

My next intention is to initialize this AugmentedMongoClient once and then pass it to different pages. I try to do this:

pages/index.py

import dash
from dash import html
from mongo_client import mngdb

dash.register_page(__name__, path='/')
print('Aaand we are here!')

def layout():
    return html.Div([
        html.H1('Hello World'),
        html.P('Trying to understand Dash imports')
    ])

But when I run python app.py I see multiple AugmentedMongoClient initialized two times, like the module is imported twice. Why is that?

Initializing AugmentedMongoClient
Aaand we are here!
Dash is running on http://localhost:8050/

 * Serving Flask app 'app' (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: on
Initializing AugmentedMongoClient
Aaand we are here!

I thought about creating AugmentedMongoClient as Singleton but I am unsure how this Singleton will behave with multiple users connected to my app? Will there be multiple Singletons? Or one instance will have to serve all users?

This is a side effect of running Dash with debug mode on. The auto-reloader (which comes from Flask) needs to run your script again in order to be able to reload itself when changes to the files are detected. See here: python - Why does running the Flask dev server run itself twice? - Stack Overflow

When you run Dash with debug mode disabled (as you should in production) this will stop. If you want to stay in debug mode but disable auto reloading, you can do app.run(use_reloader=False)

2 Likes

Thank you very much for your reply! I would also really like to understand how to pass an instance of a class with heavy initialization.

1 Like

Sorry, not sure what you mean by that. Sounds like a different question… perhaps open up a new post unpacking your question with some more context and an example.

2 Likes