Quantcast
Channel: ЁЯОЫя╕П Dash - Plotly Community Forum
Viewing all articles
Browse latest Browse all 6271
тЖз

Asynchronous notifications / output console for long callbacks - what do you think about my solution?

$
0
0

@itayma wrote:

Hi,

In a dashboard IтАЩm building I have one heavy callback that runs a series of operations and IтАЩd like to give the user some indication of the stage that is currently running.

I know we donтАЩt have asynchronous notifications yet, so I came up with a temporary solution that works but feels a bit patchy. IтАЩd love to get some feedback, especially if you see problems with such a solution or have a better one.

The idea is essentially to create a callback that calls itself as long as the process lasts, running different functions and producing matching outputs. IтАЩm using different levels in the html to bypass the restriction on dependency cycles.

HereтАЩs the code:

import time
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
from dash.exceptions import PreventUpdate

app = dash.Dash(__name__)

server = app.server

app.layout = html.Div(children=[
	html.Button('Run', id='run_button'),
	html.Div(
		id='output_container',
		children=[
			html.Div(children='', id='output_text'),
			html.Div(id='process_stage', children=-1, style={'display': 'none'})
		]
	)]
)

def dummy():
	return
	
def step1():
	time.sleep(1)

def step2():
	time.sleep(1.5)

def step3():
	time.sleep(2)
	
process_plan = [
	[dummy, ''],
	[step1, 'Running step 1...'],
	[step2, 'Running step 2...'],
	[step3, 'Running step 3...'],
	[dummy, 'Process finished.']
]
	
@app.callback([Output('process_stage', 'children'), 
			   Output('run_button', 'disabled')], 
			  [Input('run_button', 'n_clicks')])
# start the process by setting the stage to 0
def button_clicked(click):
	if not click:
		return -1, False
	else:
		return 0, True

# this callback triggers itself by returning the div container as output and getting triggered by one of its children as input
@app.callback(Output('output_container', 'children'),
			 [Input('process_stage', 'children')])
# the process runs as long as the stage (stored in a hidden div) is between 0 and the number of stages in the plan
def run_process(stage):
	if stage == -1 or stage == len(process_plan)-1:
		raise PreventUpdate
	
	process_plan[stage][0]()
	
    # the callback returns the next stage's output and runs the current stage's function, so output matches what's currently running
	return [html.Div(children=process_plan[stage+1][1], id='output_text'),
			html.Div(id='process_stage', children=stage+1, style={'display': 'none'})]

if __name__ == '__main__':
	app.run_server(debug=True)

Posts: 1

Participants: 1

Read full topic

тЖз

Viewing all articles
Browse latest Browse all 6271

Trending Articles