实时更新#

参考:Live Updates | Dash for Python Documentation | Plotly

dcc.Interval 简介#

Dash 中的组件通常通过用户交互进行更新,比如:选择下拉菜单,拖动滑块,悬停在点上。

如果您正在构建用于监视的应用程序,您可能希望每隔几秒或几分钟更新应用程序中的组件。dash_core_components.Interval 元素允许您按预定义的时间间隔更新组件。n_interval 属性是一个整数,每经过 interval 毫秒时间间隔就自动增加一次。你可以在你的应用程序的 callback 中监听这个变量,以按预先定义的时间间隔触发回调。

此示例从实时卫星反馈中提取数据,并每秒钟更新图表和文本。

import datetime

from dash import dcc, html
from plotly.subplots import make_subplots
from dash.dependencies import Input, Output

# pip install pyorbital
from pyorbital.orbital import Orbital
from app import app
import dash
dash.register_page(__name__)
satellite = Orbital('TERRA')

layout = html.Div(
    html.Div([
        html.H4('TERRA Satellite Live Feed'),
        html.Div(id='live-update-text'),
        dcc.Graph(id='live-update-graph'),
        dcc.Interval(
            id='interval-component',
            interval=1*1000,  # in milliseconds
            n_intervals=0
        )
    ])
)


@app.callback(Output('live-update-text', 'children'),
              Input('interval-component', 'n_intervals'))
def update_metrics(n):
    lon, lat, alt = satellite.get_lonlatalt(datetime.datetime.now())
    style = {'padding': '5px', 'fontSize': '16px'}
    return [
        html.Span('Longitude: {0:.2f}'.format(lon), style=style),
        html.Span('Latitude: {0:.2f}'.format(lat), style=style),
        html.Span('Altitude: {0:0.2f}'.format(alt), style=style)
    ]


# Multiple components can update everytime interval gets fired.
@app.callback(Output('live-update-graph', 'figure'),
              Input('interval-component', 'n_intervals'))
def update_graph_live(n):
    satellite = Orbital('TERRA')
    data = {
        'time': [],
        'Latitude': [],
        'Longitude': [],
        'Altitude': []
    }

    # Collect some data
    for i in range(180):
        time = datetime.datetime.now() - datetime.timedelta(seconds=i*20)
        lon, lat, alt = satellite.get_lonlatalt(
            time
        )
        data['Longitude'].append(lon)
        data['Latitude'].append(lat)
        data['Altitude'].append(alt)
        data['time'].append(time)

    # Create the graph with subplots
    fig = make_subplots(rows=2, cols=1, vertical_spacing=0.2)
    fig['layout']['margin'] = {
        'l': 30, 'r': 10, 'b': 30, 't': 10
    }
    fig['layout']['legend'] = {'x': 0, 'y': 1, 'xanchor': 'left'}

    fig.append_trace({
        'x': data['time'],
        'y': data['Altitude'],
        'name': 'Altitude',
        'mode': 'lines+markers',
        'type': 'scatter'
    }, 1, 1)
    fig.append_trace({
        'x': data['Longitude'],
        'y': data['Latitude'],
        'text': data['time'],
        'name': 'Longitude vs Latitude',
        'mode': 'lines+markers',
        'type': 'scatter'
    }, 2, 1)

    return fig

页面加载更新#

默认情况下,Dash 应用程序将 app.layout 存储在内存中。这确保当应用程序启动时,布局只计算一次。

如果你将 app.layout 设置为一个函数,那么你就可以在每次页面加载时提供动态布局。

例如,如果你的 app.layout 是这样的:

import datetime

import dash
import dash_html_components as html

app.layout = html.H1('The time is: ' + str(datetime.datetime.now()))

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

然后你的应用程序将显示应用程序启动的时间。

如果您将此更改为一个函数,那么每次刷新页面都会计算一个新的 datetime。试一试:

import datetime

import dash
import dash_html_components as html
from jupyter_dash import JupyterDash as Dash

def serve_layout():
    return html.H1('The time is: ' + str(datetime.datetime.now()))

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = Dash(__name__, external_stylesheets=external_stylesheets)

app.layout = serve_layout

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

注意

你需要写 app.layout = serve_layout,而不是 app.layout = serve_layout()。也就是说,将 app.layout 定义为实际的函数实例。

您可以将其与 性能 结合起来,每小时或每天提供一个独特的 layout,并在此期间从内存提供计算出 layout