I’m loving dash, but there definitely are some nuances to it that has me head-scratching at times. I’m trying to figure out how to break out of a while loop properly based on the state of a BooleanSwitch from the dash-daq library. What I would like to do is enter the while loop when BooleanSwitch is set to True and break out of the while loop while BooleanSwitch is set to false. Instead what I’m observing is that I get successive while loops running in parallel and the only way I can break out of them is Ctrl-C, which kills my app. I believe in a non-Dash environment you could fix this problem by making the state of the BooleanSwitch a global variable, but that isn’t recommended in dash. How would I implement this instead?
Below is some code to illustrate my issue:
boolean_switch_test.py
import dash
import dash_daq as daq
import dash_html_components as html
from dash.dependencies import Input, Output
import time
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div([
daq.BooleanSwitch(
id='my-boolean-switch',
on=False
),
html.Div(id='dummy-div',style={'display':'none'})
])
def dummy_test(on):
while on:
for i in range(1000):
print(i)
time.sleep(1)
if on==False: #since 'on' is not a global variable, this doesn't work
break
@app.callback(
Output('dummy-div', 'children'),
[Input('my-boolean-switch', 'on')])
def update_output(on):
if on:
dummy_test(on)
return None
if __name__ == '__main__':
app.run_server(debug=True)
Hi @Emil, Thanks for your reply! I’m a little confused about what you wrote, because in this case, I think what I want is synchronous operation, but what I’m observing instead is asynchronous. For instance, if I enable the boolean switch to True, wait 10 seconds, then I disable and then quickly re-enable the switch, I get the following lines to print out:
10
11
0
12
1
13
2
14
3
15
4
etc…
What I want is to find a way to break out of the while loop when I disable the switch. I’ll look into using Redis (I have no experience with this). I didn’t understand your 3rd bullet point however. Some pseudo code would be super helpful here. Thanks!!
import dash
import dash_daq as daq
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output
import time
from flask_caching import Cache
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
cache = Cache(app.server, config={
'CACHE_TYPE': 'simple',
# should be equal to maximum number of users on the app at a single time
# higher numbers will store more data in the filesystem / redis cache
'CACHE_THRESHOLD': 100
})
app.layout = html.Div([
daq.BooleanSwitch(
id='my-boolean-switch',
on=False
),
html.Div(id='dummy-div',style={'display':'none'})
])
def global_store(switch_state=None):
if switch_state is not None:
cache.set("switch-state",switch_state)
return None
else:
switch_state = cache.get("switch-state")
return switch_state
def dummy_test(state):
while state:
for i in range(1000):
print(i)
time.sleep(1)
state = global_store() # here I'm getting the boolean switch state (this is an alternative to using global variables)
if state==False:
break
@app.callback(
Output('dummy-div', 'children'),
[Input('my-boolean-switch','on')]
)
def update_store(on):
global_store(on) # here I'm setting the boolean switch state in the cache
if on:
dummy_test(on)
return None
if __name__ == '__main__':
app.run_server(debug=True)