Black Lives Matter. Please consider donating to Black Girls Code today.
Dash HoloViews is now available! Check out the docs.

Code in if __name__ == '__main__' runs twice?

My higher level goal was to use dash to take inputs and pass them to some robotics code. Along the way, I noticed some double processes going on, which probably aren’t worth getting into at the moment. For now, I’ll stick to this minimal example where I was able to reproduce:

#!/usr/bin/env python2


import dash
import dash_core_components as dcc
import dash_html_components as html


class Foo:

    def __init__(self):
        print('someone created a foo!')


class Gui:

    def __init__(self):
        self.app = dash.Dash()
        self.app.layout = html.Div(['test'])


if __name__ == '__main__':
    print('in main')
    foo = Foo()
    gui = Gui()
    gui.app.run_server(debug=True)

I’m open to suggestions on a better way to do this, and fully admit to being fairly noobish to python and definitely unfamiliar with classes. I wanted to create a class object with all of the dash stuff, so that __main__ could stay short. I’d create my gui object, be able to start the server, and all of the layout code would be generated by some class methods. My foo instance will store key variables for the robot and talk with the dash object. In essence they’ll be updating each other, with the robot taking parameters from dash, and dash plotting the data from the robot in real time. This was my stab at some way to accomplish this.

In the example above, putting dash in an object like this causes the main code to run twice, which surprised me. I get this in the terminal:

$ python class-test.py 
in main
someone created a foo!
 * Running on http://127.0.0.1:8050/ (Press CTRL+C to quit)
 * Restarting with stat
in main
someone created a foo!
 * Debugger is active!
 * Debugger PIN: 290-727-389

Why is the code evaluated twice?


Update in situ: as usual, as I’m writing what I think is a bug, I find out that it’s not at all a bug. So, how does one get dash to play nicely when there’s other code and libraries going on? In my particular case, double running my ROS code fails because it generates a node with a name, then tries to re-generate another node with the same name.

Perhaps to keep it simple, what if you had a class that did something with a file that shouldn’t exist, and you create it (or open it) upon initializing the object. Since pulling in dash appears to run twice, this would bork that. I’m sure there’s some hacky ways to check that you’re really creating the object for the first time, but I’m guessing this behavior is known and there’s a better solution.

So, this SO post came up in my search, but I was hung up on the behavior described:

If you set use_reloader to False you’ll see the behaviour go away, but then you also lose the reloading functionality.

I assumed that “reloading functionality” meant that I wouldn’t be able to update the page, refresh, live update, etc. In actuality, I believe this is purely about the functionality in which editing the file while the server is running triggers a refresh. I can absolutely live without that, so app.run_server(use_reloader=False) is what I went with.

1 Like

Yep, this this is associated with the use of the automatic reload functionality when you edit a file. Note that this is triggered by the use of debug=True to the run() method, which turns on automatic reloading (these defaults all come from Flask, as Dash passes on a bunch of params to the Flask server). So you can simply omit this param and this will also do the trick.

I’ll have to try that again. In my searching, I found some suggestions about this, but when I tried it I got the same behavior. I even did run_server([no debug]) in conjunction with app.debug = False and still had the double main going on, or that’s my recollection. I’ll give it another whirl!

Ha. Solved it! I started trying a bunch of iterations, and they all found that omitting any debug argument still caused two runs (and even Debugger is active! in the output). I googled a bit and found that this was changed quasi-recently. It must not have propagated to my pip installed version, 0.17.7:

$ grep -B2 -A2 debug ~/.local/lib/python2.7/site-packages/dash/dash.py
    def run_server(self,
                   port=8050,
                   debug=True,
                   threaded=True,
                   **flask_run_options):
        self.server.run(port=port, debug=debug, **flask_run_options)

Some fairly big changes recently, so I’d update all your dash dependencies pip list -o

dash (0.18.3)
dash-core-components (0.12.6)
dash-html-components (0.7.0)
dash-renderer (0.10.0)`

2 Likes