# Python 绘制Android CPU和内存增长曲线

### 二、具体逻辑实现详解

#### 1. CPU图表的Python实现

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import json
import sys
import time
import traceback

def startDump():
try:
imagePath = sys.argv[2]
cpuRateArray = []
timeArray = []
for cpuItem in cpuData:
cpuRateArray.append(float(cpuItem["cpuRate"]))
timeArray.append((float(float(cpuItem["time"]) - float(cpuData[0]["time"]))/1000))

plt.title("Monitor Cpu Rate")
plt.figure(figsize=(10, 8))
plt.tight_layout()
plt.plot(timeArray, cpuRateArray, c='red', label='Process CPU')
plt.ylabel("CPURate (%)", fontsize=12)
plt.xlabel("TimeRange:" + formatTime(float(cpuData[0]["time"])) + ' - ' + formatTime(float(cpuData[len(cpuData) -1]["time"])), fontsize=10)
plt.legend()
plt.savefig(imagePath)

except Exception:
print 'exeption occur:' + traceback.format_exc()

def formatTime(timeMillis):
timeSeconds = float(timeMillis/1000)
timelocal = time.localtime(timeSeconds)
timeFormat = time.strftime("%Y-%m-%d %H:%M:%S", timelocal)
return timeFormat

if __name__ == '__main__':
startDump()

#### 2. 内存图表的Python实现

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import json
import sys
import time
import traceback

def startDump():
try:
imagePath = sys.argv[2]
totalPssArray = []
nativePssArray = []
dalvikPssArray = []
timeArray = []
for memoryItem in memoryData:
totalPssArray.append(float(memoryItem["totalPss"])/1024)
nativePssArray.append(float(memoryItem["nativePss"])/1024)
dalvikPssArray.append(float(memoryItem["dalvikPss"])/1024)
timeArray.append((float(float(memoryItem["time"]) - float(memoryData[0]["time"]))/1000))

plt.title("Monitor Memory")
plt.figure(figsize=(10, 8))
plt.tight_layout()
plt.plot(timeArray, totalPssArray, c='red', label='Total Memory')
plt.plot(timeArray, nativePssArray, c='yellow', label='Native Memory')
plt.plot(timeArray, dalvikPssArray, c='blue', label='Dalvik Memory')
plt.ylabel("Memory (MB)", fontsize=12)
plt.xlabel("TimeRange:" + formatTime(float(memoryData[0]["time"])) + ' - ' + formatTime(float(memoryData[len(memoryData) -1]["time"])), fontsize=10)
plt.legend()
plt.savefig(imagePath)

except Exception:
print 'exeption occur:' + traceback.format_exc()

def formatTime(timeMillis):
timeSeconds = float(timeMillis/1000)
timelocal = time.localtime(timeSeconds)
timeFormat = time.strftime("%Y-%m-%d %H:%M:%S", timelocal)
return timeFormat

if __name__ == '__main__':
startDump()

#### 3. 实现说明

，否则会导致解析异常，传入的JSON参数也 不能直接是JSON对象
，必须转化成字符串，示例调用命令如下：

python dump_chart.py  ''  cpu_chart.png

1）采样CPU示例数据，time是设备的系统时间戳，CPU的占用率的计算可以查看前面写的： Android 性能监控之CPU监控

[
{
"time": "1589435564442.279053",
"cpuRate": "2.17"
},
{
"time": "1589435565655.333008",
"cpuRate": "3.26"
},
{
"time": "1589435566954.137939",
"cpuRate": "2.52"
},
...
]

2）采样内存示例数据，totalPss、nativePss和dalvikPss值都是从dumpsys meminfo输出的应用内存信息中截取出来的原始数据，对应“TOTAL”、“ Native Heap“、”

Dalvik Heap“字段的Pss Total值。内存信息的监控获取参考： Android 性能监控之内存监控

[
{
"time": "1589636256923.429932",
"totalPss": 177804,
"nativePss": 27922,
"dalvikPss": 10212
},
{
"time": "1589636258236.298096",
"totalPss": 178021,
"nativePss": 27850,
"dalvikPss": 9990
},
{
"time": "1589636259525.219971",
"totalPss": 177899,
"nativePss": 27742,
"dalvikPss": 9990
},
...
]

### 三、实现过程中遇到的问题

exeption occur:Traceback (most recent call last):
File "*******", line 11, in startDump
File "/usr/local/Cellar/python@2/2.7.15_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", line 287, in load
AttributeError: 'str' object has no attribute 'read'

#### 2. JSON字符串对象入参问题

  File "******", line 11, in startDump
File "/usr/local/Cellar/python@2/2.7.15_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", line 339, in loads
return _default_decoder.decode(s)
File "/usr/local/Cellar/python@2/2.7.15_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/decoder.py", line 364, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/local/Cellar/python@2/2.7.15_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/decoder.py", line 382, in raw_decode
raise ValueError("No JSON object could be decoded")
ValueError: No JSON object could be decoded

 '\'' + JSON.stringify(cpuRateJSON) + '\''

#### 3. Python需要显示声明参数的类型

Traceback (most recent call last):
File "*******", line 21, in startDump
timeArray.append(timeStamp(memoryItem["time"]))
File "*******", line 36, in timeStamp
TypeError: unsupported operand type(s) for /: 'unicode' and 'int'

#### 4. 编码导致的异常

SyntaxError: Non-ASCII character '\xe5' in file ******* on line 24, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details

#!usr/bin/python
# -*- coding: utf-8 -*-

#### 5. 保存的文件格式限制

plt.savefig (
image_path )

eps ,
pdf ,
pgf ,
png ,
ps ,
raw ,
rgba ,
svg ,
svgz 这些，不支持
jpg 图片的保存。

Traceback (most recent call last):
File "/Users/chenwenguan/Documents/AmapAuto/Project/arc-resources/script/performanceMonitor/dump_cpu_chart_image.py", line 23, in startDump
plt.savefig(image_path)
File "/usr/local/lib/python2.7/site-packages/matplotlib/pyplot.py", line 695, in savefig
res = fig.savefig(*args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/matplotlib/figure.py", line 2062, in savefig
self.canvas.print_figure(fname, **kwargs)
File "/usr/local/lib/python2.7/site-packages/matplotlib/backend_bases.py", line 2173, in print_figure
canvas = self._get_output_canvas(format)
File "/usr/local/lib/python2.7/site-packages/matplotlib/backend_bases.py", line 2105, in _get_output_canvas
.format(fmt, ", ".join(sorted(self.get_supported_filetypes()))))
ValueError: Format 'jpg' is not supported (supported formats: eps, pdf, pgf, png, ps, raw, rgba, svg, svgz)

#### 6. python-tk 依赖

Traceback (most recent call last):
File "*******", line 2, in
import matplotlib.pyplot as plt
File "/home/arc/.local/lib/python2.7/site-packages/matplotlib/pyplot.py", line 115, in
_backend_mod, new_figure_manager, draw_if_interactive, _show = pylab_setup()
File "/home/arc/.local/lib/python2.7/site-packages/matplotlib/backends/__init__.py", line 63, in pylab_setup
[backend_name], 0)
File "/home/arc/.local/lib/python2.7/site-packages/matplotlib/backends/backend_tkagg.py", line 4, in
from . import tkagg  # Paint image to Tk photo blitter extension.
File "/home/arc/.local/lib/python2.7/site-packages/matplotlib/backends/tkagg.py", line 5, in
from six.moves import tkinter as Tk
File "/home/arc/.local/lib/python2.7/site-packages/six.py", line 203, in load_module
mod = mod._resolve()
File "/home/arc/.local/lib/python2.7/site-packages/six.py", line 115, in _resolve
return _import_module(self.mod)
File "/home/arc/.local/lib/python2.7/site-packages/six.py", line 82, in _import_module
__import__(name)
File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 42, in
raise ImportError, str(msg) + ', please install the python-tk package'


python-tk依赖，执行一下命令安装：

sudo apt-get install python-tk

#### 7. Agg画布初始化配置

Traceback (most recent call last):
File "******", line 22, in startDump
plt.title("ARC Monitor Memory")
File "/home/arc/.local/lib/python2.7/site-packages/matplotlib/pyplot.py", line 1419, in title
return gca().set_title(s, *args, **kwargs)
File "/home/arc/.local/lib/python2.7/site-packages/matplotlib/pyplot.py", line 969, in gca
return gcf().gca(**kwargs)
File "/home/arc/.local/lib/python2.7/site-packages/matplotlib/pyplot.py", line 586, in gcf
return figure()
File "/home/arc/.local/lib/python2.7/site-packages/matplotlib/pyplot.py", line 533, in figure
**kwargs)
File "/home/arc/.local/lib/python2.7/site-packages/matplotlib/backend_bases.py", line 161, in new_figure_manager
return cls.new_figure_manager_given_figure(num, fig)
File "/home/arc/.local/lib/python2.7/site-packages/matplotlib/backends/_backend_tk.py", line 1046, in new_figure_manager_given_figure
window = Tk.Tk(className="matplotlib")
File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1828, in __init__
self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
TclError: no display name and no \$DISPLAY environment variable

When using Matplotlib versions older than 3.1, it is necessary to explicitly instantiate an Agg canvas

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt

#### 8. pyecharts 版本配置问题

Python2.7
3.4~3.5 版本的支持和维护，仅支持
Python3.6+。

Traceback (most recent call last):
File "*******", line 11, in
from pyecharts import options as opts
File "/usr/local/lib/python2.7/site-packages/pyecharts/__init__.py", line 1, in
from pyecharts import charts, commons, components, datasets, options, render, scaffold
File "/usr/local/lib/python2.7/site-packages/pyecharts/charts/__init__.py", line 2, in
from ..charts.basic_charts.bar import Bar
File "/usr/local/lib/python2.7/site-packages/pyecharts/charts/basic_charts/bar.py", line 17
series_name: str,
^
SyntaxError: invalid syntax