New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Asynchronous logic #57
Comments
|
Great question @thedimlebowski . Here's one way to do it. A few things to note: import dash
from dash.dependencies import Input, Output, Event
import dash_core_components as dcc
import dash_html_components as html
import datetime
import time
class Semaphore:
def __init__(self, filename='semaphore.txt'):
self.filename = filename
with open(self.filename, 'w') as f:
f.write('done')
def lock(self):
with open(self.filename, 'w') as f:
f.write('working')
def unlock(self):
with open(self.filename, 'w') as f:
f.write('done')
def is_locked(self):
return open(self.filename, 'r').read() == 'working'
semaphore = Semaphore()
def long_process():
if semaphore.is_locked():
raise Exception('Resource is locked')
semaphore.lock()
time.sleep(7)
semaphore.unlock()
return datetime.datetime.now()
app = dash.Dash()
def layout():
return html.Div([
html.Button('Run Process', id='button'),
dcc.Interval(id='interval', interval=500),
dcc.RadioItems(
id='lock',
options=[{'label': i, 'value': i} for i in ['Running...', 'Free']]),
html.Div(id='output')
])
app.layout = layout
@app.callback(
Output('lock', 'value'),
events=[Event('interval', 'interval')])
def display_status():
return 'Running...' if semaphore.is_locked() else 'Free'
@app.callback(
Output('output', 'children'),
events=[Event('button', 'click')])
def run_process():
return 'Finished at {}'.format(long_process())
app.scripts.config.serve_locally = True
if __name__ == '__main__':
app.run_server(debug=True, processes=5)This example is well suited for using dash as the control panel for hardware, where only one user or session can have access to the system at a single time. If your long running process is instead for just long-running data analysis code, I'd recommend:
Let me know if that helps! |
|
Great. Thanks a lot for the detailed example. |
|
Is there any way to farm out the async callbacks to a cluster of compute nodes? |
|
Also, is there any way to utilize persistent python processes for the callbacks (similar to how RStudio Connect offers persistent R processes)? |
|
@tantrev, you'd need to invoke a library that enables distributed task scheduling (such as Dask or Celery -- I know that Dask has good support for a range of distributed backends). So long as you manage the issue of the Dash callbacks being blocking, it's up to you how you go about scheduling distributed jobs kicked off by the callbacks. |
|
We've been using celery and redis recently with great results. See https://github.com/plotly/dash-redis-celery-periodic-updates/ for one example |
|
The example above is out of date - here is an updated version of the same example that works with dash version 1.17.0 |
Update circle

How can I handle asynchronous logic?
For instance, how can I create a button 'sleep' which writes to a div 'sleeping' for a given amount of time, and when the process is finished, writes 'awake'?
I can create a callback launching the asynchronous process with an event on the button, and write 'sleeping' to the div, but how can I change to 'awake' when the process finishes?
The text was updated successfully, but these errors were encountered: