私は最近、Pythonと、Enthought Python Distribution(無料バージョン1)に同梱されているmatplotlibモジュール(1.1.0)をいじり始めました。私は自分にできる面白いプロジェクトを考えて、次のようなものを思いつきました。
- インターネットアドレスのpingを取得します
sys.stdin
それをPythonスクリプトにパイプします
今pythonスクリプトで:
- 回答時間がない場合は、回答時間を正規表現します
NaN
。数値として0を使用します。 - matplotlibを介してデータをプロットする
- 継続的にデータを追加する
私はこれを介してpingを取得することができました:ping stackoverflow.com | pythonscript.pyはanswertimeを取得するのは特に難しいことではありませんでした。しかし、データのプロットに関しては。ハマった。matplotlib内にアニメーションモジュールがあることは知っていますが、タイマーベースのプロットはこれよりもプログラミングが難しいと思います。とにかくイベントがどのように使用されるかはわかりません。私が欲しいもの:
- sys.stdinが新しい文字列を取得し、ping時間が取得されるのを待ちます
- データ配列に追加します
- データ配列をプロットしますが、それほど簡単ではないようです。これ以外に、エラー処理はまだ行われていません。残念ながら、私はそれについて多くのグーグルをしましたが、同等のコードを見つけることができませんでした:/多分このデザインはこのようなものではありません。
誰かがこの再プロットを達成する方法を知っていますか?pingは1秒ごとにしか届かないため、効率的である必要はありません。着信stdinをバッファリングして、通常のタイマーベースのプロットを実行することを考えましたが、今はそれを実行することを考えています。
前もって感謝します、
ジョナス
Update1:
次を使用して、このエラーを取り除くことができます。
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())