Python pdb (debugger) disp equivalent?



gdb 中是否有相当于 disp 的 pdb?

例如,当我使用 gdb 调试 C 时,我可以通过键入以下内容在代码的每个"步骤"上打印变量:

disp var

当我使用 pdb 调试 python 时,我想要类似的功能,但似乎disp不存在,python pdb 文档似乎没有提供替代方案 - 但这似乎是一个奇怪的遗漏?

下面的代码使用 Python 自检功能向 PDB 模块添加两个新命令 0只需将给定的函数及其调用放在一个单独的模块中,并在开始调试之前导入此模块 - 您应该让"disp"和"undisp"命令添加和收回对变量的监视。

它的工作原理是猴子修补Python的pdb模块,该模块是用纯python编写的。

# -*- coding: utf-8 -*-
def patch_pdb():
    import pdb
    def wrap(func):
        def new_postcmd(self, *args, **kw):
            result = func(self, *args, **kw)
            if hasattr(self, "curframe") and self.curframe and hasattr(self, "watch_list"):
                for arg in self.watch_list:
                    try:
                        print >> self.stdout, "%s: %s"% (arg, self._getval(arg)) + ", ", 
                    except: 
                        pass
                self.stdout.write("n")
            return result #func(self, *args, **kw)
        return new_postcmd
    pdb.Pdb.postcmd = wrap(pdb.Pdb.postcmd)
    def do_disp(self, arg):
        if not hasattr(self, "watch_list"):
            self.watch_list = []
        self.watch_list.append(arg)
    pdb.Pdb.do_disp = do_disp
    def do_undisp(self, arg):
        if hasattr(self, "watch_list"):
            try:
                self.watch_list.remove(arg)
            except:
                pass
    pdb.Pdb.do_undisp = do_undisp
patch_pdb()
if __name__ == "__main__":
    # for testing
    import pdb; pdb.set_trace()
    a = 0
    for i in range(10):
        print i
        a += 2

不幸的是,我只能让它显示变量的状态,就像它们在执行最后一个命令之前的状态一样。(我尝试了一点,但是猴子修补 bdb 模块,这是 Pdb 的基础似乎也不起作用(。您可以尝试更改任一 pdb 中的方法。Pdb,bdb。由 wrap 修饰的 Bdb 或 cmd.Cmd 用于查找在调试的帧状态更改后调用的 Bdb 或 cmd.Cmd。

您可以设置一些别名来执行此操作:

alias n next;; p var
alias s step;; p var

打印整个变量名称列表留给读者作为练习。不幸的是,这样做意味着当您向调试器发送空行时,它执行的"最后一个命令"是p var而不是例如n。如果你想解决这个问题,那么你可以改用这组有点笨拙的 Pdb 命令:

!global __stack; from inspect import stack as __stack
!global __Pdb; from pdb import Pdb as __Pdb
!global __pdb; __pdb = [__framerec[0].f_locals.get("pdb") or __framerec[0].f_locals.get("self") for __framerec in __stack() if (__framerec[0].f_locals.get("pdb") or __framerec[0].f_locals.get("self")).__class__ == __Pdb][-1]
alias s step;; p var;; !__pdb.lastcmd = "!__pdb.cmdqueue.append('s')"
alias n next;; p var;; !__pdb.lastcmd = "!__pdb.cmdqueue.append('n')"

在 pdb 调试期间,您可以键入普通的 python 代码,而不是一个字母的命令 - 因此只需使用 print var 应该适合您。

最新更新