Как использовать FuncAnimation при использовании многопроцессорной обработки в python 3

#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. Эй, спасибо за помощь! Сейчас это работает