Background callback doesn't work with Jupyter Dash

Hi

background callback work with regular Dash(), however it doesn’t work with Jupyter Dash except all the functions have to be inside the callback. For example, in below example, there will be an error like this. How to solve this without placing all the functions inside callback function? Thanks

LongCallbackError: An error occurred inside a long callback: name 'slow_process' is not defined
Traceback (most recent call last):
  File "c:\Users\test\miniconda3\envs\dash_tf\lib\site-packages\dash\long_callback\managers\diskcache_manager.py", line 179, in run
    user_callback_output = fn(*maybe_progress, *user_callback_args)
  File "C:\Users\test\AppData\Local\Temp/ipykernel_2420/3337253254.py", line 105, in progress_bar_demo
NameError: name 'slow_process' is not defined
import time
from uuid import uuid4
import diskcache
from dash import html, DiskcacheManager, CeleryManager, Input, Output,callback
import dash_bootstrap_components as dbc
from jupyter_dash import JupyterDash

launch_uid = uuid4()
cache = diskcache.Cache("./cache")


background_callback_manager = DiskcacheManager(
    cache, cache_by=[lambda: launch_uid], expire=60
)

app = JupyterDash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP],
           background_callback_manager=background_callback_manager)

# Simple layout with Start and Cancel buttons as well as a progress bar
app.layout = html.Div(
    [
        html.Div(
            [
                dbc.Row(children=[
                    dbc.Col(),
                    dbc.Col(
                        children=[
                            html.P(id="paragraph_id", children=["Button not clicked"]),
                            # Progress component sets up the loading bar
                            dbc.Progress(id="progress-component", striped=True, value=5)
                        ]
                    ),
                    dbc.Col()
                ]
                ),
                dbc.Row(
                    children=[
                        dbc.Col(),
                        dbc.Col(
                            children=[
                                # Button kicks off the background callback
                                html.Button(id="button_id", children="Run Job!"),
                                # Button cancels the background callback
                                html.Button(id="cancel_button_id", children="Cancel Running Job!"),
                            ]
                        ),
                        dbc.Col(),
                    ]
                )
            ]
        ),
    ]
)


def calculate_percent_progress(iteration, total):
    percent = int((iteration / total) * 100)
    f_percent = f"{int(percent)} %"
    return percent, f_percent


def slow_process(set_progress):
    """
    This would be the slow function, need to set the progress on each iteration to update the progress
    bar.

    The 'set_progress' is a special argument with a function handle to update the app on current progress
    see: https://dash.plotly.com/background-callbacks

    :param set_progress:
    :return:
    """
    
    total = 10
    for i in range(total):
        time.sleep(0.5)
        percent, f_percent = calculate_percent_progress(iteration=i+1, total=total)
        set_progress([int(percent), f"{int(percent)} %"])


@callback(
    Output("paragraph_id", "children"),
    Input("button_id", "n_clicks"),
    running=[
        (Output("button_id", "disabled"), True, False),
        (Output("cancel_button_id", "disabled"), False, True),
        (
            Output("paragraph_id", "style"),
            {"visibility": "hidden"},
            {"visibility": "visible"},
        )
    ],
    cancel=[Input("cancel_button_id", "n_clicks")],
    progress=[
        Output("progress-component", "value"),
        Output("progress-component", "label")
    ],
    interval=1000,
    background=True,
    prevent_initial_call=True,
)
def progress_bar_demo(set_progress, n_clicks):

            
    slow_process(set_progress)

    return [f"Clicked {n_clicks} times"]


if __name__ == "__main__":
    # app.run(debug=True,port=8080)
    # app.run(debug=True,port=8080,use_reloader=False)
    app.run_server(debug=True,port=8080)

Hi @roudan which version of dash are you using?

Maybe helpful:

Thanks AIMPED. my dash is 2.7 version. I am wondering if I can mix use conda install dash (before) with pip install dash==2.11.0. My experience is, if package is installed by conda install. it will have issue later when using pip install to upgrade it. Any suggestion? Thanks

I’m not too familiar with conda, but you should be able to update dash thru conda.

I finally be able to install dash 2.13.0 using pip install. Then rerun the above code and I still got same error. so it still not working. Thanks for help.

What happens if you define your function slow_process() within your callback function?

if I define all functions inside callback function, then it works. That is my original question how to leave functions outside callback to make it work. I don’t want to include all functions inside callabck function since in my own example, I have multiple callbacks and multiple function. Some functions are used in multiple callback. That is why I define functions outside callback.

Try defining your functions before app instantiation, i.e. before the line:

1 Like

not working, still the same problem saying slow_process is not defined

I’m getting the same error when running “Simple Example” from Background Callbacks | Dash for Python Documentation | Plotly
where callback calls time.sleep()