【问题标题】:Matplotlib figure not responding when used with multiprocessing与多处理一起使用时,Matplotlib 图形没有响应
【发布时间】:2014-07-31 20:09:24
【问题描述】:

我正在尝试创建一个非常基本的应用程序,它将从流数据源更新 matplotlib 中的图表。数据在单独的过程中接收。但即使是最基本的显示,我的 matplotlib 图形也一直在我身上死去。 matplotlib 窗口失去交互性并变成“图 1(无响应)”。我是否需要明确地给 matplotlib 一些 CPU 时间才能使其与 multiprocessing 很好地配合使用?

这是一个基本示例,它几乎适用于 Windows 7、64 位、Python 2.7.3 32 位的所有后端。我正在使用来自here 的 scipy-stack 的非官方二进制文件:

编辑:它似乎也无法在 Ubuntu(32 位)上运行。

import time

from multiprocessing import Process

import matplotlib.pyplot as plt

def p1_func():
    while True:
        time.sleep(1)


def p2_func():
    plt.ion()
    plt.plot([1.6, 2.7])
    while True:
        time.sleep(1)

if __name__ == '__main__':

    p1_proc = Process(target=p1_func)
    p2_proc = Process(target=p2_func)

    p1_proc.start()
    p2_proc.start()

    p1_proc.join()
    p2_proc.join()

我做错了什么?

您通常如何使 matplotlib 的实时数据交互式图形和线程(多处理或其他)共存?

【问题讨论】:

  • gui 事件循环和多进程无法相处。要么将所有绘图保留在主进程中,要么在您使用的任何工具包中使用线程(但同样,将所有绘图保留在主线程上,只需进行农场工作)。
  • 有什么方法可以搅动 gui 事件循环?
  • 你可以通过改变后端matplotlib.org/faq/usage_faq.html#what-is-a-backend来解决一些问题

标签: python matplotlib multiprocessing


【解决方案1】:

join() 等待进程完成。在这种情况下,代码正在等待一个无限循环:)

基于@tcaswell 的评论,混合GUI 循环和多处理的东西是冒险的。先试试这个,而不是上面的加入代码:

   procs = [p1_proc, p2_proc]
   while any( (p.is_alive() for p in procs) ):
      time.sleep(1)

【讨论】:

  • 还是一样(没有响应)。将matplotlib显式嵌入后端窗口的真正解决方案是我可以完全控制gui事件循环吗?
【解决方案2】:

下面是一个简单的例子

import time
from multiprocessing import Process, Pipe

import numpy as np
import matplotlib.pyplot as plt

class DataStreamProcess(Process):
    def __init__(self, connec, *args, **kwargs):
        self.connec = connec
        Process.__init__(self, *args, **kwargs)

    def run(self):
        random_gen = np.random.mtrand.RandomState(seed=127260)
        for _ in range(30):
            time.sleep(0.01)
            new_pt = random_gen.uniform(-1., 1., size=2)
            self.connec.send(new_pt)


def main():
    conn1, conn2  = Pipe()
    data_stream = DataStreamProcess(conn1)
    data_stream.start()

    plt.gca().set_xlim([-1, 1.])
    plt.gca().set_ylim([-1, 1.])
    plt.gca().set_title("Running...")
    plt.ion()

    pt = None
    while True:
        if not(conn2.poll(0.1)):
            if not(data_stream.is_alive()):
                break
            else:
                continue
        new_pt = conn2.recv()
        if pt is not None:
            plt.plot([pt[0], new_pt[0]], [pt[1], new_pt[1]], "bs:")
            plt.pause(0.001)
        pt = new_pt

    plt.gca().set_title("Terminated.")
    plt.draw()
    plt.show(block=True)

if __name__ == '__main__':
    main()

【讨论】:

    【解决方案3】:

    你也可以用线程代替,我用pylab来绘图。

    import pylab
    from threading import Thread
    
    
    def threaded_function(arg):
        pylab.plot(range(1,10))
        pylab.show(block=True)
    
    
    if __name__ == "__main__":
        thread = Thread(target = threaded_function, args = (10, ))
        thread.start()
        thread.join()
        print("thread finished...exiting")
    

    【讨论】:

      【解决方案4】:

      我在multiprocessing.Pool 中使用matplotlib.animation 时遇到问题(该进程会默默地崩溃),我能够按照@deinonychusaur 的建议解决这些问题,即使用非交互式后端。

      将此添加到您的导入中:

      import matplotlib
      matplotlib.use('AGG')  # Do this BEFORE importing matplotlib.pyplot
      import matplotlib.pyplot as plt
      

      在此处了解后端:http://matplotlib.org/faq/usage_faq.html#what-is-a-backend

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-10-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-22
        • 2012-03-04
        • 1970-01-01
        相关资源
        最近更新 更多