Hello everyone! I was trying to implement a dash bootstrap component progress bar on my dash app that would show the progress of Python function that take a long time to occur. As it stands I have a single button that is used to trigger a callback which invokes the function in question. The issue I have lies with dash updating a progress bar (Progress - dbc docs) from the middle of an ongoing callback. I tried finding existing solutions to my problem and the only one I found relied on the removed EVENT dash.dependencies state. I was hoping someone could point me in the right direction on how I could go about solving this issue. If it helps, here is the existing but outdated solution I found: Asynchronous logic · Issue #57 · plotly/dash · GitHub
Edit: I saw the comment in the initial thread referencing Redis and celery but was wondering if there was another solution available?
Please let me know if I can do anything to help make my question clearer!
Here’s a self-contained example using Redis and RQ (which is maybe a little simpler than Celery?).
In general, if you have a long running task it’s best to run it in the background and have your front end periodically check for completion. I’m not aware of a way to send updates to e.g. a progress bar from inside a callback.
The callback will be blocked if you are only running a single thread. In that case, you would need to run the background process async to avoid the block. Here is a small example using the (default) threaded mode of Dash,
import time
import dash_html_components as html
import dash_core_components as dcc
from dash.exceptions import PreventUpdate
from dash_extensions.enrich import Output, Dash, Trigger, FileSystemCache
steps, sleep_time = 100, 0.1
# Create example app.
app = Dash(prevent_initial_callbacks=True)
app.layout = html.Div([
html.Button("Click me", id="btn"), html.Div(id="progress"), html.Div(id="result"),
dcc.Interval(id="interval", interval=500)
])
# Create a server side resource.
fsc = FileSystemCache("cache_dir")
fsc.set("progress", None)
@app.callback(Output("result", "children"), Trigger("btn", "n_clicks"))
def run_calculation():
for i in range(steps):
fsc.set("progress", str((i + 1) / steps)) # update progress
time.sleep(sleep_time) # do actual calculation (emulated by sleep operation)
return "done"
@app.callback(Output("progress", "children"), Trigger("interval", "n_intervals"))
def update_progress():
value = fsc.get("progress") # get progress
if value is None:
raise PreventUpdate
return "Progress is {:.0f}%".format(float(fsc.get("progress")) * 100)
if __name__ == '__main__':
app.run_server()
Thanks for your information, It can let me update progress value periodically without a callback.
One more problem:
When I used FileSystemCache lib, and save “cache_dir” on my local side, I met this warning message=>
delete key ‘progress’ → [WinError 32] The process cannot access the file because it is being used by another process: 'cache_dir\3c709b10a5d47ba33d85337dd9110917’
Do you have any solutions that can remove this warning message? thanks.