Why is my reload-hash constantly firing in debug=False mode

Hello,

I’m trying to use Dash app to visualize a graph if a condition is met in another python file. I’d like to avoid running the file twice which happens when I set debug=True in app.run_server method (solution here) But when I set it to False, I’m getting "GET /_reload-hash HTTP/1.1" 200 - every 3 seconds. I’m not sure if it’s connected, but in documentation I’ve found a line

  • dev_tools_hot_reload_interval`, float, interval in seconds at which the renderer will request the reload hash and update the browser page if it changed. (default=3).

But I don’t think that page changes. And even so, it’s defaulted to False if debug=False.

My code:

import copy
from dash import Dash, dcc, html, Input, Output
import dash_cytoscape as cyto
import networkx as nx

from for_dash import get_edges

app = Dash(__name__)

edges, edge_labels, b = get_edges()
G = nx.Graph()
G.add_edges_from(edges)
pos = nx.spring_layout(G)
pos_param = 2000
nodes = [
    {
        "data": {"id": node, "label": node},
        "position": {"x": pos_param * p[0], "y": pos_param * p[1]},
        "classes": "green",
    }
    for node, p in pos.items()
]
for n in nodes:
    if n["data"]["id"] in b:
        n["classes"] = "red"

edges = [
    {"data": {"source": edge[0], "target": edge[1], "label": label}}
    for edge, label in edge_labels.items()
]

my_stylesheet = [
    # Group selectors
    {"selector": "node", "style": {"content": "data(label)"}},
    # Class selectors
    {"selector": ".red", "style": {"background-color": "red", "line-color": "red"}},
    {
        "selector": ".green",
        "style": {"background-color": "green", "line-color": "green"},
    },
]

app.layout = html.Div(
    [
        cyto.Cytoscape(
            id="graph",
            elements=nodes + edges,
            stylesheet=my_stylesheet,
            style={"width": "100%", "height": "600px"},
            layout={"name": "preset"},
        ),
        dcc.Checklist(
            id="connections",
            options=[
                "Adres",
                "Telefon",
                "Email",
                "Prepaid",
                "Reverse prepaid",
                "Same prepaid",
                "Przelewy",
                "GRYF",
                "GIIF",
            ],
            value=[
                "Adres",
                "Telefon",
                "Email",
                "Prepaid",
                "Reverse prepaid",
                "Same prepaid",
                "Przelewy",
                "GRYF",
                "GIIF",
            ],
        ),
        # dcc.RadioItems(
        #     id='radio-update-layout',
        #     value='preset',
        #     options=[
        #         {'label': name.capitalize(), 'value': name}
        #         for name in ['grid', 'random', 'circle', 'cose', 'concentric']
        #     ]
        # ),
        html.Br(),
        dcc.Slider(
            0.1,
            5,
            id="pos_param",
            value=1,
            marks={0.1: "0.1", 0.5: "0.5", 1: "1", 1.5: "1.5", 2: "2", 5: "5"},
        ),
    ]
)


@app.callback(
    Output("graph", "elements"),
    Input("connections", "value"),
    Input("pos_param", "value"),
)
def update_edges(conn, p):
    updated_edges = copy.deepcopy(edges)
    updated_nodes = copy.deepcopy(nodes)
    updated_edges = [
        edge for edge in updated_edges if any(v in edge["data"]["label"] for v in conn)
    ]
    updated_nodes = [
        node
        for node in updated_nodes
        if any(node["data"]["id"] in e["data"].values() for e in updated_edges)
    ]
    for node in updated_nodes:
        node["position"]["x"] *= p
        node["position"]["y"] *= p
    return updated_nodes + updated_edges


if __name__ == "__main__":
    app.run_server(debug=True, port=1234)

@edit
I’ve changed the code a bit to run the app from the other python file and this time I was getting refreshes every minute, for 4 minutes. Then I waited 2 minutes more but the refresh didn’t come up, so I’ve changed a slider value manually and now I’m getting refreshes every 3 seconds again.
@edit2
I’ve ran the scripts a couple times more and the problem doesn’t seem to occur again. I’d very much like to know why that happened, but I guess I’ll delete this post tomorrow if everything runs smoothly from now on.

You’ll want to refresh the browser when making those kinds of changes, in order for the client to stop sending hot-reload pings to the server. The client has its own state for these kind of app properties, perhaps you still had a client session running that had yet to get new config values from the server?

2 Likes

I believe I might’ve had another session opened in another tab. Later when I tested, I had only 1. Seems to have been the case, thanks for the explanation!

1 Like

I’m having a similar problem, and I’m looking for a programmatic explanation (which I have not found despite quite some looking). I want to start a Dash app from the command line, and I want it to load into an already-open browser tab pointed at http://127.0.0.1:8050/

When I set debug=True this works as expected. But I want to make it work with debug=False, and I don’t want to require user intervention to hit reload in order for it to do what it should be doing. What else am I missing?

Not sure if that’s something you’ll be able to do. Firstly, that tab will need have opened the app previously in order for it to have pulled down some client state that allows it to know where to be listening for changes to.

Secondly, since Dash doesn’t use web sockets, you’ll need some kind of periodic heartbeat request from the Dash client to the server to see if it needs to issue a reload. This is exactly what the hot reload feature of debug mode gives you. The only option I can think of is just setting dev_tools_hot_reload=True, rather than the full debug mode. See the docs at Dash Dev Tools | Dash for Python Documentation | Plotly

Try passing use_reloader=True in app.run(), along with debug=False, dev_tools_hot_reload=True, and dev_tools_silence_routes_logging=True if you want to hide logging in the console.