Построение графика данных в реальном времени из источника с высокой пропускной способностью
Поскольку gen. py код этого ответа быстро рос, я написал собственную версию gen_own.py ниже, которая по сути вводит задержку в 1 мс перед записью новых данных в файл. Я также адаптировал кодplot.py и написал свой собственныйplot_own.py, по существу добавив операторы отладки. Хотя я пытался прочитать документацию по нескольким компонентам строки f.seek(0, io.SEEK_END), есть еще несколько моментов, которые я не понимаю. Вот все вопросы, которые у меня есть
- Самый очевидный (который, безусловно, поможет понять остальные вопросы): как мы можем адаптироватьplot_own.py для работы с gen_own.py (с более медленным потоком данных)
- Причина, по которой plot_own.py не работает с gen_own.py, что поток данных gen_own.py слишком медленный?
- В выводеplot_own. py запускаются одновременно с gen_own.py, почему индексы, заданные командами f.seek и f.tell, различаются (f.seek(0, io.SEEK_END): 36998872 и f.tell(): 36998936)? Это потому, что даже после выполнения строки f.seek(0, io.SEEK_END) эта команда постоянно ищет конец файла даже после выполнения?
- Аналогично этому, почему выходные данные f.readline() и данные, хранящиеся в данных, отличаются?
data: 1731141285.629006385803 0.946414017554
- В выводеplot_own.py выполняется одновременно с gen_own.py, хотя позиция обоих f.seek(0, io.SEEK_END): 162626 и f.tell(): 162626 совпадают, в функции f.readline() есть вывод и ничего не сохранено в данных, почему?
#!/usr/bin/env python3
import time
import random
LIMIT_TIME = 100 # s
DATA_FILENAME = "data.txt"
def gen_data(filename, limit_time):
start_time = time.time()
elapsed_time = time.time() - start_time
old_time = time.time()
with open(filename, "w") as f:
while elapsed_time < limit_time:
new_time = time.time()
if new_time > old_time + 0.001:
f.write(f"{time.time():30.12f} {random.random():30.12f}\n") # produces 64 bytes
f.flush()
old_time = time.time()
elapsed = old_time - start_time
gen_data(DATA_FILENAME, LIMIT_TIME)
для конкурентоспособности здесь приведен код gen.py (скопирован из исходного вопроса)
#!/usr/bin/env python3
import time
import random
LIMIT_TIME = 100 # s
DATA_FILENAME = "data.txt"
def gen_data(filename, limit_time):
start_time = time.time()
elapsed_time = time.time() - start_time
with open(filename, "w") as f:
while elapsed_time < limit_time:
f.write(f"{time.time():30.12f} {random.random():30.12f}\n") # produces 64 bytes
f.flush()
elapsed = time.time() - start_time
gen_data(DATA_FILENAME, LIMIT_TIME)
Вот кодplot_own.py:
#!/usr/bin/env python3
import io
import time
import matplotlib.pyplot as plt
import matplotlib as mpl
import matplotlib.animation
BUFFER_LEN = 64
DATA_FILENAME = "data.txt"
PLOT_LIMIT = 20
ANIM_FILENAME = "video.gif"
fig, ax = plt.subplots(1, 1, figsize=(10,8))
ax.set_title("Plot of random numbers from `gen.py`")
ax.set_xlabel("time / s")
ax.set_ylabel("random number / #")
ax.set_ylim([0, 1])
def get_data(filename, buffer_len, delay=0.0):
with open(filename, "r") as f:
print("f.seek(0, io.SEEK_END): " + str(f.seek(0, io.SEEK_END)))
data = f.read(buffer_len)
print("f.tell(): " + str(f.tell()))
print("f.readline(): " + f.readline())
print("data: " + data)
if delay:
time.sleep(delay)
return data
def animate(i, xs, ys, limit=PLOT_LIMIT, verbose=False):
# grab the data
try:
data = get_data(DATA_FILENAME, BUFFER_LEN)
if verbose:
print(data)
x, y = map(float, data.split())
if x > xs[-1]:
# Add x and y to lists
xs.append(x)
ys.append(y)
# Limit x and y lists to 10 items
xs = xs[-limit:]
ys = ys[-limit:]
else:
print(f"W: {time.time()} :: STALE!")
except ValueError:
print(f"W: {time.time()} :: EXCEPTION!")
else:
# Draw x and y lists
ax.clear()
ax.set_ylim([0, 1])
ax.plot(xs, ys)
# save video (only to attach here)
#anim = mpl.animation.FuncAnimation(fig, animate, fargs=([time.time()], [None]), interval=1, frames=3 * PLOT_LIMIT, repeat=False)
#anim.save(ANIM_FILENAME, writer='imagemagick', fps=10)
#print(f"I: Saved to `{ANIM_FILENAME}`")
# show interactively
anim = mpl.animation.FuncAnimation(fig, animate, fargs=([time.time()], [None]), interval=1)
plt.show()
plt.close()
Вот результат выполненияplot_own.py при одновременном запуске с gen.py
f.seek(0, io.SEEK_END): 36998872
f.tell(): 36998936
f.readline(): 1731141285.629011392593 0.423847536979
data: 1731141285.629006385803 0.946414017554
f.seek(0, io.SEEK_END): 37495182
f.tell(): 37495246
f.readline(): 1731141285.670451402664 0.405303398216
data: 1731141285.670446395874 0.103460518242
f.seek(0, io.SEEK_END): 38084306
f.tell(): 38084370
f.readline(): 1731141285.719735860825 0.360983611461
data: 1731141285.719730854034 0.318057761442
Вот результат выполненияplot_own.py при одновременном запуске с gen_own.py
W: 1731141977.7246473 :: EXCEPTION!
f.seek(0, io.SEEK_END): 156426
f.tell(): 156426
f.readline():
data:
W: 1731141977.7611823 :: EXCEPTION!
f.seek(0, io.SEEK_END): 158472
f.tell(): 158472
f.readline():
data:
W: 1731141977.79479 :: EXCEPTION!
f.seek(0, io.SEEK_END): 160518
f.tell(): 160518
f.readline(): 1731141977.828338146210 0.165056626254
data:
W: 1731141977.8283837 :: EXCEPTION!
f.seek(0, io.SEEK_END): 162626
f.tell(): 162626
f.readline():
data:
W: 1731141977.8621912 :: EXCEPTION!
f.seek(0, io.SEEK_END): 164734
f.tell(): 164734
f.readline():
data:
Подробнее здесь: https://stackoverflow.com/questions/791 ... plot-of-hi
Мобильная версия