Plot.ly Dash Examples

Dash’s design often causes many callbacks to depend on the same value. This leads to the threads/processes that are handling the callback to perform the same computation. By using jitcache’s KVStore we can prevent this wasteful effort.

Configuration

You must use gunicorn’s preload option when using multiple processes to ensure that the KVStore is shared. Otherwise a KVStore object will be created for each process.

Use the following command to start your server:

gunicorn --preload app:server

You can find more details here http://docs.gunicorn.org/en/stable/settings.html#preload-app

Callback Memoization

examples_dash/callback_memoize/app.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import dash
import dash_html_components as html
from jitcache import Cache
import dash_core_components as dcc


cache = Cache()

app = dash.Dash(__name__)

server = app.server
app.layout = html.Div(
    children=[
        html.Div(id="output-container-dropdown1", children=[]),
        html.Div(id="output-container-dropdown2", children=[]),
        dcc.Dropdown(
            options=[
                {"label": "New York City", "value": "NYC"},
                {"label": "Montréal", "value": "MTL"},
                {"label": "San Francisco", "value": "SF"},
            ],
            value="MTL",
            id="dropdown",
        ),
    ]
)


@app.callback(
    dash.dependencies.Output("output-container-dropdown1", "children"),
    [dash.dependencies.Input("dropdown", "value")],
)
@cache.memoize
def update_output1(input_dropdown):
    print("run1")

    return input_dropdown


@app.callback(
    dash.dependencies.Output("output-container-dropdown2", "children"),
    [dash.dependencies.Input("dropdown", "value")],
)
@cache.memoize
def update_output2(input_dropdown):
    print("run2")

    return input_dropdown


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

General Function Memoization

examples_dash/function_memoize/app.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import dash
import dash_html_components as html
import time
from jitcache import Cache


cache = Cache()

app = dash.Dash(__name__)

server = app.server
app.layout = html.Div(
    children=[
        html.Button("Submit", id="button"),
        html.Div(id="output-container-button1", children=[]),
        html.Div(id="output-container-button2", children=[]),
    ]
)


# This is only called once per click
@cache.memoize
def slow_fn(input_1, input_2):
    print("Slow Function Called")
    time.sleep(1)
    return input_1 * input_2


@app.callback(
    dash.dependencies.Output("output-container-button1", "children"),
    [dash.dependencies.Input("button", "n_clicks")],
)
def update_output1(n_clicks):
    input_1 = n_clicks if n_clicks is not None else 0
    input_2 = 2

    value = slow_fn(input_1, input_2)

    return f"Value is {value} and the button has been clicked {n_clicks} times"


@app.callback(
    dash.dependencies.Output("output-container-button2", "children"),
    [dash.dependencies.Input("button", "n_clicks")],
)
def update_output2(n_clicks):
    input_1 = n_clicks if n_clicks is not None else 0
    input_2 = 2

    value = slow_fn(input_1, input_2)

    return f"Value is {value} and the button has been clicked {n_clicks} times"


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