GDB Python美化打印的非阻塞pyplot GUI

3 投票
1 回答
1151 浏览
提问于 2025-04-18 14:33

我想用matplotlib来可视化一些数据,以便在调试时查看。参考了这个页面:用Python和Numpy在gdb调试器中分析C/C++矩阵 - CodeProject,一切运行得还不错,除了matplotlib的图形界面会阻塞GDB的命令行。这意味着如果我打开了图形界面窗口,GDB的命令行就会被锁住,我无法在GDB中输入任何命令,直到我关闭pyplot窗口。

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

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,就会打开一个不阻塞的图形界面,看起来不错,GDB的命令行仍然可以接受命令,一切正常。

但是问题出现在我关闭绘图窗口后,当我再次运行source test-pyplot.py时,GDB就卡住了。

我在Windows下使用的是Python 2.7.6,并且我发现matplotlib默认使用tkAgg作为绘图后端,所以我想看看普通的tk GUI窗口是否也会出现这种情况。这里有另一个测试的Python文件,命名为“test-tk.py”,内容如下:

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的小技巧来让这个过程简单一些。

另外,图形界面工具包通常会干扰SIGCHLD,这会导致gdb出问题。所以你需要用一些小手段来解决这个问题。

你可以看看我是如何解决这些问题的,参考我做的gdb图形界面的概念验证:https://gitorious.org/gdb-gui

撰写回答