我最近开始修补 Python 和 Enthought Python Distribution(免费版本之一)附带的 matplotlib 模块(1.1.0)。我想到了一个我可以做的有趣的项目,并想出了这样的事情:
- 获取互联网地址的 ping
- 通过管道将其
sys.stdin
导入python脚本
现在在python脚本中:
- 正则表达式回答时间,如果没有回答时间:使用
NaN
or 只是 0 作为数字 - 通过 matplotlib 绘制数据
- 不断添加数据
我设法通过以下方式获得 ping:ping stackoverflow.com | python script.py 得到应答时间并不是特别难。但是在绘制数据时。我被困住了。我知道 matplotlib 中有一个动画模块,但我认为基于计时器的绘图会比这更难编程,而且我不知道如何使用事件。我想要的是:
- 等待 sys.stdin 获得一个新字符串,从而获得 ping 时间
- 将其添加到数据数组
- 绘制数据数组 但似乎没那么容易。除此之外,错误处理还没有完成。不幸的是我找不到任何类似的代码,虽然我做了很多谷歌搜索:/也许这个设计不是这样的。。
有谁知道如何完成这个重新绘制?它不需要高效,因为 ping 每隔一秒左右才会出现一次。我考虑过缓冲传入的标准输入并执行基于计时器的常规绘图,但我现在有了这样做的想法。
先感谢您,
乔纳斯
更新1:
我可以使用以下方法消除此错误:
l1.set_xdata(range(len(data)))
之前l1.set_ydata(..)
,但它仍然没有绘制任何内容,并且窗口也没有响应。至少它显示了绘图轴。
代码
import sys
import re
import numpy as np
import matplotlib.pyplot as plt
def main():
if sys.stdin.isatty():
print "Please use a pipe as stdin\nExample: ping stackoverflow.com | python script.py"
return 0
regex = re.compile('time=(\d+.\d+)')
data = []
fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_yscale('linear') # or log
ax.grid(True)
l1, = ax.plot(data)
fig.show()
while True:
#get ping, if no string: stream has ended
line = sys.stdin.readline()
if line == '':
break
#conversion: 64 bytes from 127.0.0.1: icmp_seq=0 ttl=45 time=100.873 ms --> 100.873
match = regex.findall(line)
number = 0.
if len(match) > 1:
raise ValueError()
if len(match) == 1:
try:
number = float(match[0])
except ValueError as e:
print e
#add number to array, plot the data
data.append(number)
l1.set_xdata(range(len(data)))
l1.set_ydata(data)
ax.relim()
ax.autoscale()
plt.draw()
fig.canvas.flush_events()
return 0
if __name__ == '__main__':
sys.exit(main())