Python 由和间隔组件更新的全局变量
当我的dash应用程序启动时,一个计算复杂的函数会创建一个全局变量(dat)。我希望dat定期更新,但不是通过任何用户操作。我知道由于内存共享的方式,普通的python全局变量不适合在dash中使用,因此我使用一个隐藏的div来存储定期更新的数据 我不希望在每个用户启动应用程序时更新数据,而是希望在后台进行更新,最好使用更新的数据更新所有用户的应用程序。如果应用程序必须更新页面刷新,也可以,但更新的数据将可供所有用户使用 我在下面举了一个例子,它执行我想做的任务,问题是如果数据是字符串或numpy数组,那么将数据存储在div中就可以了,但是如果数据结构更复杂,比如pandas数据帧(参见注释的代码行)或pandas数据帧字典,那么应用程序将运行,但该页面不会加载到浏览器中(加载布局时出错)。也许记忆是解决办法,尽管我所看到的所有例子都与此有细微的不同,以至于我看不出如何使用它。使用隐藏的div对我来说似乎有点像是一种黑客,但在绘图图腾的帮助页面中推荐使用 所以我的问题是,如何使用比字符串或数组更复杂的数据结构在dash中创建和更新全局变量Python 由和间隔组件更新的全局变量,python,plotly-dash,Python,Plotly Dash,当我的dash应用程序启动时,一个计算复杂的函数会创建一个全局变量(dat)。我希望dat定期更新,但不是通过任何用户操作。我知道由于内存共享的方式,普通的python全局变量不适合在dash中使用,因此我使用一个隐藏的div来存储定期更新的数据 我不希望在每个用户启动应用程序时更新数据,而是希望在后台进行更新,最好使用更新的数据更新所有用户的应用程序。如果应用程序必须更新页面刷新,也可以,但更新的数据将可供所有用户使用 我在下面举了一个例子,它执行我想做的任务,问题是如果数据是字符串或nump
import dash
from dash.dependencies import Input, Output, Event
import dash_html_components as html
import dash_core_components as dcc
from datetime import datetime
import numpy as np
import pandas as pd
app = dash.Dash(__name__)
def compute_expensive_data():
t=datetime.now()
dat = np.array([t.minute, t.second])
#d = {'time' : pd.Series(np.array([t.minute, t.second]), index=['minute', 'second'])}
#dat = pd.DataFrame(d)
return dat
dat = compute_expensive_data()
print(dat)
app.layout = html.Div([
html.H3('Original Time: Minute = ' + str(dat[0]) + ': Second = ' + str(dat[1])),
#html.H3('Original Time: Minute = ' + str(dat['time']['minute']) + ': Second = ' + str(dat['time']['second'])),
html.Div(id='title-line-children'),
dcc.RadioItems(
id='time-dropdown',
options=[
{'label': 'Minute', 'value': 'minute'}, {'label': 'Second', 'value': 'second'},
],
value='minute'
),
# Hidden div inside the app that stores the intermediate value
html.Div(id='intermediate-value', style={'display': 'none'}, children = dat),
dcc.Interval(
id='interval-component',
interval=20*1000 # 20 seconds in milliseconds
)
])
@app.callback(
Output('title-line-children', 'children'),
[Input('time-dropdown', 'value'), Input('intermediate-value', 'children')])
def render(value,dat1):
if value == 'minute':
printStr = str(dat1[0])
#printStr = str(dat1['time']['minute'])
outStr = 'Minute = ' + printStr
elif value == 'second':
printStr = str(dat1[1])
#printStr = str(dat1['time']['second'])
outStr = 'Second = ' + str(dat1[1])
return outStr
@app.callback(Output('intermediate-value', 'children'),
events=[Event('interval-component', 'interval')])
def update_global_var():
return compute_expensive_data()
if __name__ == '__main__':
app.run_server(debug=True)
好的,所以答案很直截了当。我只需要jsonify我的数据帧。然后它基本上只是一个可以保存在隐藏div中的字符串
import dash
from dash.dependencies import Input, Output, Event
import dash_html_components as html
import dash_core_components as dcc
from datetime import datetime
import numpy as np
import pandas as pd
app = dash.Dash(__name__)
def compute_expensive_data():
t=datetime.now()
d = {'time' : pd.Series(np.array([t.minute, t.second]), index=['minute', 'second'])}
dat = pd.DataFrame(d).to_json()
return dat
dat = compute_expensive_data()
print(dat)
app.layout = html.Div([
html.H3('Original Time: Minute = ' + str(pd.read_json(dat)['time']['minute']) + ': Second = ' + str(pd.read_json(dat)['time']['second'])),
html.Div(id='title-line-children'),
dcc.RadioItems(
id='time-dropdown',
options=[
{'label': 'Minute', 'value': 'minute'}, {'label': 'Second', 'value': 'second'},
],
value='minute'
),
# Hidden div inside the app that stores the intermediate value
html.Div(id='intermediate-value', style={'display': 'none'}, children = dat),
dcc.Interval(
id='interval-component',
interval=20*1000 # 20 seconds in milliseconds
)
])
@app.callback(
Output('title-line-children', 'children'),
[Input('time-dropdown', 'value'), Input('intermediate-value', 'children')])
def render(value,dat1):
if value == 'minute':
printStr = str(pd.read_json(dat1)['time']['minute'])
outStr = 'Minute = ' + printStr
elif value == 'second':
printStr = str(pd.read_json(dat1)['time']['second'])
outStr = 'Second = ' + printStr
return outStr
@app.callback(Output('intermediate-value', 'children'),
events=[Event('interval-component', 'interval')])
def update_global_var():
return compute_expensive_data()
if __name__ == '__main__':
app.run_server(debug=True)
更新至破折号1.8的答案:
import dash
from dash.dependencies import Input, Output
import dash_html_components as html
import dash_core_components as dcc
from datetime import datetime
import numpy as np
import pandas as pd
app = dash.Dash(__name__)
def compute_expensive_data():
t=datetime.now()
d = {'time' : pd.Series(np.array([t.minute, t.second]), index=['minute', 'second'])}
dat = pd.DataFrame(d).to_json()
return dat
dat = compute_expensive_data()
print(dat)
app.layout = html.Div([
html.H3('Original Time: Minute = ' + str(pd.read_json(dat)['time']['minute']) + ': Second = ' + str(pd.read_json(dat)['time']['second'])),
html.Div(id='title-line-children'),
dcc.RadioItems(
id='time-dropdown',
options=[
{'label': 'Minute', 'value': 'minute'}, {'label': 'Second', 'value': 'second'},
],
value='minute'
),
# Hidden div inside the app that stores the intermediate value
html.Div(id='intermediate-value', style={'display': 'none'}, children = dat),
dcc.Interval(
id='interval-component',
interval=2*1000, # 20 seconds in milliseconds
n_intervals=0
)
])
@app.callback(
Output('title-line-children', 'children'),
[Input('time-dropdown', 'value'), Input('intermediate-value', 'children')])
def render(value,dat1):
if value == 'minute':
printStr = str(pd.read_json(dat1)['time']['minute'])
outStr = 'Minute = ' + printStr
elif value == 'second':
printStr = str(pd.read_json(dat1)['time']['second'])
outStr = 'Second = ' + printStr
return outStr
@app.callback(Output('intermediate-value', 'children'),
[Input('interval-component', 'n_intervals')])
def update_global_var(n):
return compute_expensive_data()
if __name__ == '__main__':
app.run_server(debug=False)
那么这会在页面重新加载时重新更新全局变量吗?我基本上有一个更新的JSON,我希望dash应用程序在每次重新加载页面时都重新加载最新版本。。。。