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)