2017-10-15 28 views
0

當我的短劃線應用程序啓動時,全局變量由一個計算量很大的函數創建(dat)。我想要定期更新dat,但不是任何用戶操作。我知道普通的python全局變量不適合在短劃線中使用,因爲共享內存的方式,所以我使用隱藏的div來存儲定期更新的數據。全局變量更新者和時間間隔組件

我不想在每個用戶啓動應用程序時更新數據,而是希望更新在後臺進行,並且最好使用更新的數據更新所有用戶應用程序。如果應用程序必須刷新頁面才能更新,但更新的數據將適用於所有用戶。

我已經在下面的例子中執行了我想要做的任務,麻煩的是,如果它是字符串或numpy數組,但是如果數據結構更復雜一個熊貓數據框(請參閱註釋的代碼行)或熊貓數據框字典,然後該應用程序將運行,但該頁面不會在瀏覽器中加載(加載佈局時出錯)。也許記憶是解決方案,儘管我看到的所有例子似乎都與此有微妙的不同,所以我看不出它是如何使用的。隱藏的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() 
    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) 

回答

0

好的,所以答案很簡單。我只需要對我的數據框進行裁切。然後它基本上只是一個可以保存在隱藏的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)