之前写了个服务器磁盘监控的脚本,每天将磁盘的使用情况通过电子邮件发送出来,通过paramiko.SSHClient()将磁盘使用情况报错到一个DataFrame对象中,然后通过DataFrame的实例方法to_html直接转换成html,最后通过MIMEText发送html到邮箱中。
通过以上方法,在邮件正文中看到的是表格,在服务器较多时,不够直观。所以想改造成直接显示柱状图。但是邮件正文一般都无法运行js代码,所以使用js写的表格转换柱状图无法使用,所以只能用纯html来实现。
从Hadoop 50070页面的磁盘状况表格中得到灵感,可以使用表格嵌套和背景颜色来实现柱状图。下图中Used列,就是还有表格嵌套来实现的柱状图,我只需将横向柱状转换成纵向即可。
先收到写也demo
<!--这是一个用表格嵌套来实现两个标签的柱状图demo-->
<br>10.1.1.1<br>
<table border="1px" style="table-layout:fixed >
<tbody border="1px" width="100px" height="200px" >
<!--柱状图1-->
<td>
<table border="1px" width="100px" height="200px">
<tbody>
<tr>
<td height ="" cellspacing="0" class="perc_filled" bgcolor="" align="center"></td>
</tr>
<tr>
<td height ="99%" cellspacing="0" class="perc_filled" bgcolor="#FF0000" align="center">99%</td>
</tr>
</tbody>
</table>
</td>
<!--柱状图2-->
<td>
<table border="1px" width="100px" height="200px">
<tbody>
<tr>
<td height ="" cellspacing="0" class="perc_filled" bgcolor="" style="word-break:break-all;" align="center"></td>
</tr>
<tr>
<td height ="0%" cellspacing="0" class="perc_filled" bgcolor="#FF0000" style="word-break:break-all;" align="center" >0%</td>
</tr>
</tbody>
</table>
</td>
<tr>
<!--标签-->
<td style="word-break:break-all;" align="center" >/</td>
<td style="word-break:break-all;" align="center" >/opt/data01</td>
</tr>
</tbody>
</table>
demo的效果如下:
这个demo还有一些问题,比如使用率为0%是,显示的却为一半,这个在实际的代码中解决。
先设计一个函数,接收两个参数,一个是柱状图的标题,如上面的10.1.1.1,另一个参数是DataFrame对象,这个对象包含两列,第一列是数据标签,第二列是数据,第二列的数据格式为带符合的比例数据:如50%。
因为可能会有多个挂载点,且数量不一定。所以需要一个html模板,然后通过format方法替换模板中的占位符。
python代码如下:
# -*- coding: utf-8 -*-
"""
Created on %(2018-01-20)s
@author: %(周小科)s
"""
import pandas as pd
import numpy as np
html_modle="""
<br><b>{title}</b><br>
<table border="1px" style="table-layout:fixed >
<tbody border="1px" width="100px" height="200px" >
<!--<td height ="" cellspacing="0" class="perc_filled" bgcolor="" align="center"> 使用率</td> -->
{histogramTdHtml}
<tr>
<!--<td style="word-break:break-all;" align="center" >挂载点</td> -->
{labHtml}
</tr>
</tbody>
</table>
"""
histogramTdHtmlTempletNonzero="""
<td>
<table width="100px" height="200px">
<tbody>
<tr>
<td height ="" cellspacing="0" class="perc_filled" bgcolor="" align="center"></td>
</tr>
<tr>
<td height ="{percent}" cellspacing="0" class="perc_filled" bgcolor="{color}" align="center">{percentText}</td>
</tr>
</tbody>
</table>
</td>
"""
histogramTdHtmlTempletZero="""
<td>
<table width="100px" height="200px">
<tbody>
</tbody>
</table>
</td>
"""
labHtmlTemplet="""
<td style="word-break:break-all;" align="center" >{lable}</td>
"""
def DataFrame2HistogramHtml(title,df):
"""
将pandas中的DataFrame转换成柱状图html代码
title:标题。这个图的标题
df:传入DataFrame对象,要求这个对象有两列,第一列是标签,第二列是百分比数据,带%的 入 50%。index必须从0开始
"""
pd.DataFrame()
histogramTdHtml=""
labHtml=""
##大于一个阈值,就用红色或橙色显示
for i in range(0,len(df)):
lable=df.loc[i][0]
percent=df.loc[i][1]
percentText=percent
percentData=int(percent.replace("%",""))
#print(percentData)
#print("print(percent)",percent)
labHtml=labHtml+labHtmlTemplet.format(lable=lable)
color="#0099FF"
#默认是条形图颜色为蓝色,如果超过50%则为黄色,如果超过90%则为红色
if(percentData>90):
color="#FF0000"
elif(percentData>50):
color="#FFCC00"
#如果百分比为0%,则使用histogramTdHtmlTempletZero模板
if(percentData==0):
#print(percent)
histogramTdHtmlTemplet=histogramTdHtmlTempletZero
percentText=""
elif(percentData<10):
histogramTdHtmlTemplet=histogramTdHtmlTempletNonzero
percentText=""
else:
histogramTdHtmlTemplet=histogramTdHtmlTempletNonzero
histogramTdHtml=histogramTdHtml+histogramTdHtmlTemplet.format(percent=percent,color=color,percentText=percentText)
#print(histogramTdHtml)
#print(labHtml)
html=html_modle.format(title=title,histogramTdHtml=histogramTdHtml,labHtml=labHtml)
#print(html)
return html
def main():
s1=pd.Series(np.array(["a","b","c","d","e"]))
s2=pd.Series(np.array(["51%","0%","50%","1%","91%"]))
df=pd.DataFrame({"m":s1,"u":s2});
print(df)
print(len(df))
for i in range(1,len(df)+1):
print(i)
html=DataFrame2HistogramHtml("10.1.1.1",df)
f=open(r"C:\histogramTdHtml.html","w")
f.write(html)
f.close
if __name__=='__main__':
#RESULT_STR=''
main()
该代码中包含了调试数据,可以直接运行(前提是装了pandas、numpy库),并将html代码写入C:\histogramTdHtml.html 读者可以自行修改main方法中的测试代码。测试效果如下:
这个方法也还有写待改进的地方,比如柱状图的高和宽,可以参数化,使其可以更加通用。目前高和宽是在html模板中写死的,如果需要调整,会比较麻烦