Closed
Description
Describe your context
Dash Callback Example 4: Progress Bar from https://dash.plotly.com/background-callbacks
dash 2.6.1
dash-bootstrap-components 1.2.1
dash-core-components 2.0.0
dash-daq 0.5.0
dash-html-components 2.0.0
dash-table 5.0.0
- OS: Windows
- Browser Chrome
- Version 104.0.5112.81
Describe the bug
using background callbacks does not work with pages.
not using pages the code runs correctly
app.py
import os
import dash
from dash import DiskcacheManager, CeleryManager, html, page_container
# code to test without pages
# import pages.page as page
if 'REDIS_URL' in os.environ:
# Use Redis & Celery if REDIS_URL set as an env variable
from celery import Celery
celery_app = Celery(__name__, broker=os.environ['REDIS_URL'], backend=os.environ['REDIS_URL'])
background_callback_manager = CeleryManager(celery_app)
else:
# Diskcache for non-production apps when developing locally
import diskcache
cache = diskcache.Cache("./cache")
background_callback_manager = DiskcacheManager(cache)
app = dash.Dash(__name__,
use_pages=True,
# code to test without pages
# use_pages=False,
background_callback_manager=background_callback_manager)
app.layout = html.Div(
page_container
# code to test without pages
# page.layout()
)
if __name__ == "__main__":
app.run_server(debug=True)
pages/page.py
import dash
from dash import Input, Output, html
import time
dash.register_page(__name__, path='/page')
def layout():
return html.Div([
html.Div(
[
html.P(id="paragraph_id", children=["Button not clicked"]),
html.Progress(id="progress_bar", value="0"),
]
),
html.Button(id="button_id", children="Run Job!"),
html.Button(id="cancel_button_id", children="Cancel Running Job!"),
])
@dash.callback(
output=Output("paragraph_id", "children"),
inputs=Input("button_id", "n_clicks"),
background=True,
running=[
(Output("button_id", "disabled"), True, False),
(Output("cancel_button_id", "disabled"), False, True),
(
Output("paragraph_id", "style"),
{"visibility": "hidden"},
{"visibility": "visible"},
),
(
Output("progress_bar", "style"),
{"visibility": "visible"},
{"visibility": "hidden"},
),
],
cancel=Input("cancel_button_id", "n_clicks"),
progress=[Output("progress_bar", "value"), Output("progress_bar", "max")],
prevent_initial_call=True
)
def update_progress(set_progress, n_clicks):
total = 5
for i in range(total + 1):
set_progress((str(i), str(total)))
time.sleep(1)
return f"Clicked {n_clicks} times"
Expected behavior
Ability to use background callbacks AND pages
Screenshots
Metadata
Assignees
Labels
No labels
Activity
T4rk1n commentedon Sep 7, 2022
Seems like the pickling calls
register_page
when unpickling the function definition on the workers, adding a context var to check if inside a background callback could fix this.roykoand commentedon Apr 3, 2024
@T4rk1n You've done a great work on solving this issue! It helped a lot :)
Do you have any documentation on ignoring a register page?
Is it correct that as of now the only solution is
dash.testing.ignore_register_page
context manager?