✊🏿 Black Lives Matter. Please consider donating to Black Girls Code today.
⚡️ Concerned about the grid? Kyle Baranko teaches how to predicting peak loads using XGBoost. Register for the August webinar!

Use app.run_server in callback

Hi all,

I hope someone can help me. I’m developing an app with Dash, in which one can upload some files at runtime using dcc.Upload. Then, I need to create some callbacks, depending on the uploaded file. Unfortunately, I can’t define the callbacks before running the server (app.run_server(debug=True)), since they depend on the uploaded data.

My idea was to “restart” the whole app in a callback, e.g. create a new app with all the callbacks, and then run the new app by app.run_server(debug=True). Unfortunately, I always get a ValueError: signal only works in main thread.

The following callback is triggered when I selected the files and hit an “Upload Button”.

@app.callback(Output("dummy-div", "children"),
              [Input("upload-button", "n_clicks")])
    def update(upload_button):
        # A new layout is calculated from the uploaded data
        layout = setup_new_dash_layout()
        # A new app is created in my dash_app_handler
        dash_app_handler.create_new_app()
        # The layout of this new app will be set
        dash_app_handler.set_layout(layout)
        # The callbacks depending on the new data will be created
        add_callbacks(dash_app_handler)
        # The new app should be restarted again
        dash_app_handler.run_server()

This is how dash_app_handler looks like:

class DashAppHandler():
    def __init__(self):
        self.app = dash.Dash(name=__name__,
                             external_stylesheets=external_stylesheets,
                             )
        self._add_empty_layout()

    def run_server(self, debug=True):
        self.app.run_server(
            debug=debug,
        )

    def set_layout(self, layout):
        self.app.layout.children = layout

    def create_new_app(self):
        self.app = dash.Dash(name=__name__, external_stylesheets=external_stylesheets)
        self._add_empty_layout()

    def _add_empty_layout(self):
        self.app.layout = html.Div(children=[], id='app_layout')

The easiest solution I think would be to add callbacks to the existing running app. But I haven’t found a way to modify the callbacks in a running server (app.run_server).

Any ideas how to get it work? Or any other ideas how to solve my problem?

Any help is highly appreciated! Thanks in advance!

I think there probably is some simpler solution than restarting the server.

Could you give a minimal (toy) example of a callback that would depend on the uploaded data in a such way that it would be impossible to define it before running the server?

Hi np8,

Thank you very much for the response and for trying to help with the issue.

Some background
I can upload up to 4 different files. Each file contains different x,y data with a corresponding title. For simplicity, after decoding the uploaded files and storing them in e.g. uploaded_file, the structure of one file looks like this: {'data_name1': [x_values1, y_values1], 'data_name2': [x_values2, y_values2], ...}. The files which will be uploaded have often different data_names, and, of course, different data values (x_values, y_values).

I now display the graphs (which will be created from the data of the files) in columns. (i.e. 1 file == 1 colum, 2 files == 2 columns, etc.).

For each file, I create a dashtable that displays all the data_names of an uploaded file. What I want is, that when clicking on one of the cells and hitting a “Plot” button, the corresponding data of the selected cell will be plotted using Plotly in a graph. So when having e.g. four files, four tables are displayed in 4 columns. Below the tables, a graph is displayed.
Now, when selecting a cell of a file (that contains the name) and then hitting the “Plot” button, I will plot the corresponding data in the corresponding graph.
The problem is now, that I have a varying amount of files in Dash. For each file, I need to add a “Plot” button.

Of course, I could before running the server add always the callbacks for four log files, but then I always got “id not found errors”, because the ids of the buttons do not exist yet.

(This is only one example, I have some more cases of callbacks that are dependent on the files, but I hope it is clear what I want to achieve)

So, I assume I need to somehow restart the server in order to be able to change the app itself…

Thanks for helping!

Hi @gaaroai ,

At first glance to me it seems that this should be doable without any special tricks in Dash.

Could you put here a simple MWE that produces the id not found error, and also some example data files?