#python #numpy #multiprocessing #streaming
Вопрос:
надеюсь, у вас все отлично получается. Я совсем новичок в Python и работаю над крошечным проектом клиент — сервер, где я получаю данные от клиента, и цель состоит в том, чтобы сервер отображал эти данные в графической форме в режиме реального времени. Это код из серверной части, с которой у меня сейчас проблемы.
import socket import sys import math import numpy as np import struct import time import os import ctypes as c import multiprocessing import matplotlib.pyplot as plt from matplotlib import animation from matplotlib import style HOST = '127.0.0.1' PORT = 6543 receive_size = 4096 def run_server(shared_data_time, shared_data_signal): with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server: server.bind((HOST, PORT)) server.listen() conn, addr = server.accept() with conn: print(f"Connected by {addr}") while True: data = conn.recv(receive_size) if len(data) == 4096: payload = np.frombuffer(data, dtype = 'float64') print(payload) print('received data') deinterleaved = [payload[idx::2] for idx in range(2)] shared_data_time = deinterleaved[0] shared_data_signal = deinterleaved[1] print(f'received {len(data)} bytes') if __name__ == '__main__': HOST = '127.0.0.1' PORT = 6543 receive_size = 4096 shared_data_time = multiprocessing.Array('f', 2048) shared_data_signal = multiprocessing.Array('f', 2048) process1 = multiprocessing.Process(target = run_server, args =(shared_data_time, shared_data_signal)) process1.start() def animate(i, shared_data_time, shared_data_signal): ax1.clear() ax1.plot(shared_data_time, shared_data_signal) style.use('fivethirtyeight') fig = plt.figure() ax1 = fig.add_subplot(1,1,1) ani = animation.FuncAnimation(fig, animate, fargs = (shared_data_time, shared_data_signal), interval = 100) plt.show()
Связь между сервером и клиентом работает, но я получаю только пустой график, без актуализации. Не могли бы все мне помочь? Я был бы вам очень признателен.
Спасибо
Комментарии:
1. Я думаю, что вы просто переписываете общий массив в своем дочернем процессе, а не обновляете значения.
shared_data_time[:] = deinterleaved[0]
Вместо этого попробуйте скопировать значения в массив
Ответ №1:
не имея доступа к серверу, к которому вы подключаетесь, трудно определить точную проблему, но, пожалуйста, посмотрите этот пример, который я привел для анимации данных, поступающих из дочернего процесса через общие multiprocessing.Array
:
import multiprocessing as mp import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation import numpy as np from time import sleep, time def server(arr_x, arr_y): #tie shared buffers to numpy arrays x = np.frombuffer(arr_x.get_obj(), dtype='f4') y = np.frombuffer(arr_y.get_obj(), dtype='f4') T = time() while True: t = time() - T #elapsed time #we should technically lock access while we're writing to the array, # but mistakes in the data are not real important if it's just a gui. x[:] = np.linspace(t, t np.pi*2, len(x)) #update data in shared array y[:] = np.sin(x) sleep(1/30) #data updating faster or slower than animation framerate is not a big issue... if __name__ == "__main__": fig = plt.figure() ax = plt.subplot() #init data arr_x = mp.Array('f', 1000) #type "d" == np.dtype("f8") arr_y = mp.Array('f', 1000) #tie shared buffers to numpy arrays x = np.frombuffer(arr_x.get_obj(), dtype='f4') y = np.frombuffer(arr_y.get_obj(), dtype='f4') #calculate initial value x[:] = np.linspace(0, np.pi*2, len(x)) y[:] = np.sin(x) #daemon process to update values (server) mp.Process(target=server, args=(arr_x, arr_y), daemon=True).start() #plot initial data because we need a line instance to update continually line = ax.plot(x, y)[0] #fps counting vars last_second = time() last_frame = 0 def animate(frame, x, y): global last_second, last_frame #might be cleaner to wrap animate and use nonlocal rather than global, # but it would be more complicated for just this simple example. #set data with most recent values line.set_data(x, y) line.axes.set_xlim(x[0], x[999]) #periodically report fps interval = time() - last_second if interval gt;= 1: print("fps: ", (frame-last_frame) / interval) last_second = time() last_frame = frame ani = FuncAnimation(fig, animate, fargs=(x, y), interval = 20) plt.show()
Подсчет кадров в секунду, очевидно, может быть легко удален, и преобразование общих массивов в массивы numpy не является строго необходимым, но я нахожу, что с ним легче работать, и это не сложно.
Комментарии:
1. Эй, спасибо за помощь! Сейчас это работает