多进程展示Matplotlib图表

5

我尝试打开多个图表,但遇到了一些问题。当我试图使用线程创建绘图时,Python 会先打开一些窗口,然后关闭除第一个之外的所有窗口。

在另一个问题中,推荐我使用 multiprocessing,我已经尝试过了。代码没有错误,只是没有显示任何图表。
在着手处理主要项目之前,我想先尝试让一些非常简单的东西起作用。

# Import the necessary packages and modules
import matplotlib.pyplot as plt
import numpy as np


#from threading import Thread
import multiprocessing

def plot(datax, datay, name):
    # Prepare the data
    x = datax
    y = datay**2
    # Plot the data
    plt.scatter(x, y, label=name)

    # Add a legend
    plt.legend()

    # Show the plot
    plt.show()



#plot(3,3,)
'''
for i in range(10):
    t = Thread(target=plot, args=(i,i+1,i,))
    t.start()
    '''
for i in range(2):
    p = multiprocessing.Process(target=plot, args=(i, i, i))
    p.start()

更新: 由于某些原因,多进程再次停止工作。我尝试创建一个名为multiP()的函数来打开这些进程,但是当我添加input('value: ')时它没有起作用。因为我无法弄清如何向特定线程发送数据,所以我将像这样保存数据:dat = [[x,y0,y1,...yn],[x,y0,y1,...yn],...],每个绘图进程都会检查是否有东西被添加到dat中。

import matplotlib.pyplot as plt
import numpy as np

import multiprocessing
#multiprocessing.freeze_support() # <- may be required on windows

def plot(datax, datay, name):
    x = datax
    y = datay**2
    plt.scatter(x, y, label=name)
    plt.legend()
    plt.show()

def multiP():
    if __name__ == "__main__":   
        for i in range(2):
            p = multiprocessing.Process(target=plot, args=(i, i, i))
            p.start()
if True:
    #input('Vlaue: ') # while commented plots are shown
    multiP()


嗯,我基本上只需要能够通过pyusb获取数据并将其实时绘制到多个图表中(或尽可能接近实时)。 - user169808
我怀疑在此处使用的多进程技术对于实时绘图并不会有帮助,因为一旦进程启动后,您就需要与其进行通信。 - ImportanceOfBeingErnest
你知道实时绘制多个图表或类似功能的其他方法吗? - user169808
我的意思是你仍然可以尝试一下,我可能在这里是错误的。我肯定会先按顺序更新它们,只有在确实不够快时才考虑其他选项。 - ImportanceOfBeingErnest
我该如何更新它们?说实话,我对多进程有点困惑。我尝试使用multiprocessing.Queue().put(val),但我一直收到BrokenPipeError: [WinError 232] The pipe is being closed的错误提示,这让我很烦恼。如果我在if语句外面放置val='',并在plot()函数内部将x=val,那么就不会打开任何窗口,也不会出现任何错误,因此我认为多线程没有读取val并且没有返回任何错误。 - user169808
显示剩余2条评论
2个回答

4
下面的代码会生成两个所需的图像。
import matplotlib.pyplot as plt
import numpy as np

import multiprocessing
#multiprocessing.freeze_support() # <- may be required on windows

def plot(datax, datay, name):
    x = datax
    y = datay**2
    plt.scatter(x, y, label=name)
    plt.legend()
    plt.show()

def multiP():
    for i in range(2):
        p = multiprocessing.Process(target=plot, args=(i, i, i))
        p.start()

if __name__ == "__main__": 
    input('Value: ') 
    multiP()

谢谢你的代码,但我又遇到了问题。在for循环之前,我添加了x = input('Value: '),现在图形再次无法显示。我在循环中添加了print('hi')来查看它是否进入(它确实进入了)。 - user169808
这个应该放在只作为脚本执行的部分;我在答案中加了一个注释。 - ImportanceOfBeingErnest
再次强调,输入必须是代码的一部分,只有在用作脚本时才更新。 - ImportanceOfBeingErnest

0

参考BeingErnest的重要性答案,我在下面留下一个只显示一个窗口并等待窗口关闭的实现,这非常方便。每次调用它时,都会显示具有相应图像的新窗口(每个图像将启动一个新进程)。 在调试期间停在某个断点时,我经常用它来查看图像。

# Library packages needed
import numpy as np
import datetime
import sys
import queue
import multiprocessing

# Plot related packages
import matplotlib.pyplot as plt


def showImage(img: np.ndarray, title: str = str(datetime.datetime.today())):
    """Show an image in a new process without blocking. Usefull for debugging.

    Args:
        img (np.ndarray): Image to be shown
        title (str, optional): Title to be shown. Defaults to
    str(datetime.datetime.today()).
    """

    def plot(q, title):
        fig = plt.figure()
        fig.suptitle(title)
        try:
            q.get(True, 2.0)  # Wait a couple of seconds
        except queue.Empty:
            print('Not image received to plot...quitting')
            sys.exit()

        plt.imshow(img)
        plt.show()
        sys.exit()

    # Create a queue to share data between process
    q = multiprocessing.Queue()

    # Create and start the process
    proc = multiprocessing.Process(None, plot, args=(q, title))
    proc.start()
    q.put(img)

要运行它,只需将其保存到show_image.py文件中并调用即可

from show_image.py import showImage
show_image(img, title)

我遇到了一个错误: AttributeError: 无法pickle本地对象'showImage.<locals>.plot' - shz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接