非阻塞的Pyplot GUI用于GDB Python漂亮打印机。

3

我只是想使用matplotlib来可视化一些调试数据。遵循这个页面:Analyzing C/C++ matrix in the gdb debugger with Python and Numpy - CodeProject,它可以正常工作,除非matplotlib GUI阻塞了GDB的命令行。这意味着如果我保持GUI窗口打开,GDB的命令行将被冻结,我无法在GDB命令中输入任何内容,直到关闭pyplot窗口。

为了解决这个问题,我尝试在另一个线程中运行绘图代码。为简化测试用例,我创建了一个名为“test-pyplot.py”的简单python源代码文件,其内容如下:

import numpy as np
from matplotlib import pyplot as plt
from threading import Thread

class MyThread (Thread):

    def __init__(self, thread_id):
        Thread.__init__(self)
        self.thread_id = thread_id

    def run(self):
        x = np.arange(0, 5, 0.1);
        y = np.sin(x)
        plt.plot(x, y)
        plt.show(block = True) #this cause the mainloop

thread1 = MyThread(1)
thread1.start()

现在,在GDB命令行下,我只需键入:source test-pyplot.py,一个非阻塞的GUI将会打开并且看起来不错,GDB的命令行仍然可以接收命令,目前为止一切都很好。但是问题出现了,当我关闭绘图窗口后,再次运行source test-pyplot.py时,这时,GDB就卡住了。我使用的是Windows下的Python2.7.6,并且我看到matplotlib默认使用tkAgg作为绘图后端,因此我想看看是否会对普通的tk GUI窗口产生影响。这里有另一个名为“test-tk.py”的测试Python文件,其内容如下:
from Tkinter import *
from threading import Thread
class App():
    def __init__(self):
        self.g=Tk()
        self.th=Thread(target=self.g.mainloop)
        self.th.start()
    def destroy(self):
        self.g.destroy()
a1 = App()

如果我在GDB提示符下运行命令source test-tk.py,将会出现一个tk窗口,GDB仍然活动(未冻结),我可以关闭tk窗口,然后再次输入命令source test-tk.py,一切都正常工作,GDB不会挂起。我甚至可以在没有关闭第一个tk窗口的情况下两次运行命令source test-tk.py,那么就会出现两个tk窗口。
问题:如何以非阻塞模式正确显示matplotlib pyplot图形,而不会挂起GDB?谢谢。 通常,plt.show会在内部调用Tkinter包的mainloop函数,这是一个事件循环。 matplotlib确实有一个名为交互模式的选项,可以通过调用`plt.ion()`来启用,但它无法解决我的问题。
1个回答

2

存在多个问题。顺便说一下,我认为我曾经在之前研究过这个确切的问题,搜索gdb bugzilla。

无论如何,一个问题是你应该将GUI运行在单独的线程中。这可以避免缺乏主循环集成。虽然这有点难以编程,但你可以使用Python技巧使其变得更加轻松。

此外,GUI工具包通常会干扰SIGCHLD,这会破坏gdb。因此,你需要使用一种hack来处理它。

你可以在我的概念证明gdb GUI中看到我是如何解决这些问题的:https://gitorious.org/gdb-gui


嗨,汤姆,谢谢你的回复。在搜索gdb bugzilla时,我找到了一个:gdb hangs after plotting with matplotlib,你也提到了SIGCHLD。我浏览了一下你的gdb-gui源代码,你创建了一个.so文件来解决这些信号问题,但我理解这种hack对我来说有点难度,因为它似乎只适用于非Windows系统。顺便说一下,你建议在单独的线程中运行GUI,是的,我确实在单独的线程中运行了我的python绘图代码,并且所有的主循环函数都在单独的线程中运行。 - ollydbg23
看起来Ipython已经解决了这个问题,请参考此帖子:https://sourceforge.net/p/matplotlib/mailman/message/9333243/和[使用matplotlib绘图](http://heim.ifi.uio.no/inf3330/scripting/doc/python/ipython/node14.html),我也看到Wing IDE也已经解决了这个问题,请参考:http://wingware.com/doc/howtos/matplotlib - ollydbg23
嗨,汤姆,你说得对,在我的代码中,GUI是在主线程中创建的,而GUI事件循环则在单独的线程中运行。但是,如果我将所有代码都改为像你在The Cliffs of Inanity › 10. Wacky stuff - tromey.com中创建的页面一样在单独的线程中运行,我仍然会遇到问题。我发现很多shell都有“集成GUI事件循环”,请参见:IPython GUI Support Notes — IPython 3.0.0-dev documentation - ollydbg23
IEP可以集成事件循环(http://www.iep-project.org/iepwizard.html#configuring-shells),而pydev可以具有GUI事件循环集成(http://pydev.org/manual_adv_interactive_console.html#gui-event-loop-integration),那么GDB能否实现这一点呢? - ollydbg23

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