matplotlib show 挂起线程
matplotlib show hangs the thread
我有两个通过套接字进行通信的进程。
第一个进程先打开第二个进程,方法如下:
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) 没有帮助)。
如果不看代码,很难准确判断您在做什么,但我认为这是预期的正确行为。
如果您在没有交互模式的情况下使用 plt.show
,则发生的情况是 GUI 事件循环正在控制您的子进程中的线程。这个事件循环是接收 mouse/keyboard 事件来使图形交互的。因此,只要 window 打开,GUI 就会控制你的第二个进程的主线程,它似乎会忽略你的其他消息。
或者,当您使用 plt.ion()
时,GUI 事件循环不会 运行,而是依靠其他东西定期启动它(在命令提示符下,这是通过 PyOS_InputHook
机制)所以虽然你的第二个进程正在获取你的消息,但没有显示任何内容(因为 GUI 事件循环没有 运行 重新绘制 window)并且 window 似乎已经死了(因为事件循环不消耗输入事件)。
您要么需要在第二个过程中滚动您自己的事件循环(因为您正在实施 RPC,这不是一个坏主意)并定期调用 canvas.flush_events
(这将 运行 事件循环直到所有未决事件都已用完),让 GUI 框架处理从引导进程获取事件,然后(可能)将跟随进程上的消息处理推送到子线程(如果这样做,请非常小心,只使用 draw_idle
请求重新绘制图形,GUI 不喜欢您尝试从非主线程绘制)。
我使用 pyqtgraph
库连续绘制从 Windows 下的 COM 端口 运行 接收到的值,因为我永远无法 matplotlib
可靠地更新实时尽管数小时的尝试。 pyqtgraph
附带了一个很好的示例文件,我将其用作模板,然后可以针对我的用例进行修改,经过几次尝试后我就可以可靠地工作了。
所以我
- 一个 python 线程在
while
循环中读取 COM 端口,该线程在一端填充 deque
并在另一端弹出一个元素。
- 然后在图形更新函数中每 20 毫秒左右将双端队列复制到图形中。
我有两个通过套接字进行通信的进程。 第一个进程先打开第二个进程,方法如下:
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) 没有帮助)。
如果不看代码,很难准确判断您在做什么,但我认为这是预期的正确行为。
如果您在没有交互模式的情况下使用 plt.show
,则发生的情况是 GUI 事件循环正在控制您的子进程中的线程。这个事件循环是接收 mouse/keyboard 事件来使图形交互的。因此,只要 window 打开,GUI 就会控制你的第二个进程的主线程,它似乎会忽略你的其他消息。
或者,当您使用 plt.ion()
时,GUI 事件循环不会 运行,而是依靠其他东西定期启动它(在命令提示符下,这是通过 PyOS_InputHook
机制)所以虽然你的第二个进程正在获取你的消息,但没有显示任何内容(因为 GUI 事件循环没有 运行 重新绘制 window)并且 window 似乎已经死了(因为事件循环不消耗输入事件)。
您要么需要在第二个过程中滚动您自己的事件循环(因为您正在实施 RPC,这不是一个坏主意)并定期调用 canvas.flush_events
(这将 运行 事件循环直到所有未决事件都已用完),让 GUI 框架处理从引导进程获取事件,然后(可能)将跟随进程上的消息处理推送到子线程(如果这样做,请非常小心,只使用 draw_idle
请求重新绘制图形,GUI 不喜欢您尝试从非主线程绘制)。
我使用 pyqtgraph
库连续绘制从 Windows 下的 COM 端口 运行 接收到的值,因为我永远无法 matplotlib
可靠地更新实时尽管数小时的尝试。 pyqtgraph
附带了一个很好的示例文件,我将其用作模板,然后可以针对我的用例进行修改,经过几次尝试后我就可以可靠地工作了。
所以我
- 一个 python 线程在
while
循环中读取 COM 端口,该线程在一端填充deque
并在另一端弹出一个元素。 - 然后在图形更新函数中每 20 毫秒左右将双端队列复制到图形中。