matplotlib show挂起线程

时间:2016-03-20 23:21:28

标签: multithreading matplotlib interactive hang

我有两个通过套接字进行通信的进程。 第一个过程首先按以下方式打开第二个过程:

def run_command(cmd)
    subprocess.call(cmd, shell=True)

cmd = 'python full_path_to_script.py'
thread = Thread(target=run_command, args=(cmd,)
thread.start()

然后打开连接:

from multiprocessing.connection import Client
address = ('localhost', port_number)
conn = Client(address, authkey=b'some_password')

当第一个想要绘制某些内容时,它会向第二个消息发送消息,该消息将解密消息并使用matplotlib绘制数据。这个想法是第一条消息打开一个图像,其他消息发送更新到图像。 问题是pyplot.show挂起第二个进程,现在无法获取新消息。我尝试使用pyplot.ion(),但后来这个数字被冻结了(它没有帮助添加pyplot.pause(0.001))。

2 个答案:

答案 0 :(得分:2)

如果没有看到代码,很难确切地说出你在做什么,但我认为这是预期和正确的行为。

如果在没有交互模式的情况下使用plt.show发生的事情是GUI事件循环正在控制子进程中的线程。此事件循环是接收鼠标/键盘事件以使图形交互的内容。因此,只要该窗口打开,GUI就会控制第二个进程的主线程,它似乎会忽略您的其他消息。

或者,当您使用plt.ion()时,GUI事件循环不会运行,而是依赖于其他内容来定期启动它(在命令提示符下这是通过PyOS_InputHook机制完成的),所以尽管你的第二个进程是收到你的消息,没有显示任何内容(因为GUI事件循环没有运行以重新绘制窗口),窗口似乎已经死了(因为事件循环没有消耗输入事件)。

您需要在第二个进程中滚动自己的事件循环(因为您正在实现RPC,这不是一个坏主意)并定期调用canvas.flush_events(将运行事件循环,直到所有挂起的事件都用尽) ,让GUI框架处理从引导进程获取事件,打开(可能)将关注进程上的消息处理推送到子线程(如果这样做非常小心,只使用draw_idle请求一个数字重绘,GUI不喜欢你试图从主线程绘制。)

答案 1 :(得分:1)

我使用pyqtgraph lib来连续绘制从Windows运行的COM端口收到的值,因为尽管经过数小时的尝试,我仍然无法实时可靠地更新matplotlibpyqtgraph附带了一个很好的示例文件,我将其用作模板,然后可以修改我的用例,这样我就可以在几次尝试后可靠地工作。

所以我有

  • 一个python线程在while循环中读取COM端口,该线程在一端填充deque并在另一端弹出一个元素。
  • 然后在图表更新功能中每20毫秒左右将deque复制到图表中。