当我尝试Live Update时,我迷迷糊糊,因此决定将其作为备忘录的备忘录。
本文摘要
- 当我尝试使用Dash定期更新图表时(出现问题),出现错误
- 原因:缺少"事件"
- 对应:将时间间隔组件设置为输入
什么是Dash
Python Web应用程序框架。使用Plotly轻松可视化。
详情请见官方。
背景
我通过参考有关制作Web应用程序的文章来尝试对图表进行实时更新,该文章可以通过此Plotly Dash轻松查看。
我遇到以下错误,有点麻烦。 ..
所引用文章的相关部分是以下修饰符。
1 2 3 | @app.callback(Output('live-update-text', 'children'), events=[Event('interval-component', 'interval')]) def update_graph_live(): |
原因
根据Google老师的说法,"事件"似乎已从Dash的0.37版中消失。
还有其他人遇到麻烦了。
如何修复ImportError:无法从Dashly(python)导入Dash中的名称"事件"?
我应该怎么办?当我调查时,该方法是正式编写的。
信件
相应的方法与官方的实时更新组件相同,并且将事件重写为Input。
具体来说,我对上述相关部分进行了如下编辑。
1 2 3 | @app.callback(Output('live-update-text', 'children'), [Input('interval-component', 'n_intervals')]) def update_graph_live(n): |
如果您修改参考文章中的"系统监视器"以使其与ver0.37一起使用,它将如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 | import jupyterlab_dash #今回はJupyterlabを使用 import dash import dash_html_components as html #from dash.dependencies import Input, Output, Event from dash.dependencies import Input, Output #Eventはもういない。。 import dash_core_components as dcc import datetime import plotly import numpy as np import pandas as pd import psutil viewer = jupyterlab_dash.AppViewer() colors = { 'background': '#111111', 'text': '#7FDBFF' } app = dash.Dash(__name__) app.layout = html.Div(children=[ html.Div([ html.H4('システムモニタ'), html.Div(id='live-update-text'), dcc.Graph(id='live-update-graph'), html.H4('プロセスリスト'), html.Div(id='live-update-proc'), dcc.Interval( id='interval-component', interval=1*1000, # in milliseconds n_intervals=0 #公式に沿って追加 ) ]) ], style={'backgroundColor': colors['background'], 'color': colors['text']} ) class Context: def __init__(self): self.t = [] self.cpu = [] self.per_cpu = [[] for x in range(psutil.cpu_count())] self.mem = [] @classmethod def append_data(cls, d1, d2): n = len(d1) if n > 100: del d1[0:n - 99] d1.append(d2) context = Context() # The `dcc.Interval` component emits an event called "interval" # every `interval` number of milliseconds. # Subscribe to this event with the `events` argument of `app.callback` @app.callback(Output('live-update-text', 'children'), #events=[Event('interval-component', 'interval')]) [Input('interval-component', 'n_intervals')]) #def update_metrics(): def update_metrics(n): now = datetime.datetime.now() hour, minute, second = now.hour, now.minute, now.second style = {'padding': '5px', 'fontSize': '16px'} return [ html.Span('CPU: {}%'.format(context.cpu[-1]), style=style), html.Span('Memory: {}%'.format(context.mem[-1]), style=style) ] # Multiple components can update everytime interval gets fired. @app.callback(Output('live-update-graph', 'figure'), #events=[Event('interval-component', 'interval')]) [Input('interval-component', 'n_intervals')]) #def update_graph_live(): def update_graph_live(n): # global context context.append_data(context.t, datetime.datetime.now()) context.append_data(context.cpu, psutil.cpu_percent()) for data, pct in zip(context.per_cpu, psutil.cpu_percent(percpu=True)): context.append_data(data, pct) context.append_data(context.mem, psutil.virtual_memory().percent) # Create the graph with subplots fig = plotly.tools.make_subplots(rows=2, cols=1, vertical_spacing=0.2) fig['layout']['margin'] = { 'l': 30, 'r': 10, 'b': 30, 't': 10 } fig['layout']['plot_bgcolor'] = colors['background'] fig['layout']['paper_bgcolor'] = colors['background'] fig['layout']['font'] = {'color': colors['text']} fig['layout']['legend'] = {'x': 0, 'y': 1, 'xanchor': 'left'} fig['layout']['yaxis1'].update(range=[0, 100]) fig['layout']['yaxis2'].update(range=[0, 100]) fig.append_trace({ 'x': context.t, 'y': context.cpu, 'name': 'cpu', 'mode': 'lines', 'type': 'scatter', }, 1, 1) for i, y in enumerate(context.per_cpu): fig.append_trace({ 'x': context.t, 'y': y, 'name': 'cpu {}'.format(i), 'mode': 'lines', 'type': 'scatter', }, 1, 1) fig.append_trace({ 'x': context.t, 'y': context.mem, 'name': 'memory', 'mode': 'lines', 'type': 'scatter', 'fill': 'tonexty', }, 2, 1) return fig def get_proc_df(): def get_proc(proc): try: pinfo = proc except psutil.NoSuchProcess: pass return (pinfo.pid, pinfo.name(), pinfo.memory_percent(), pinfo.cpu_percent()) data = [get_proc(proc) for proc in psutil.process_iter()] df = pd.DataFrame(data, columns=['pid', 'name', 'memory', 'cpu']) df['memory'] = df['memory'].map(lambda x: '{:.2f}%'.format(x)) df['cpu'] = df['cpu'] / psutil.cpu_count() df['cpu'] = df['cpu'].map(lambda x: '{:.2f}%'.format(x)) return df.sort_values('cpu', ascending=False) @app.callback(Output('live-update-proc', 'children'), #events=[Event('interval-component', 'interval')]) [Input('interval-component', 'n_intervals')]) #def generate_table(): def generate_table(n): df = get_proc_df() max_rows = 10 return html.Table( # Header [html.Tr([html.Th(col) for col in df.columns])] + # Body [html.Tr([ html.Td(df.iloc[i][col], style={'width': '8em'}) for col in df.columns ]) for i in range(min(len(df), max_rows))] ) #if __name__ == '__main__': # app.run_server(debug=True) viewer.show(app) |