是否有相当于disp
gdb的pdb?
例如,当我使用 gdb 调试 C 时,我可以通过键入以下内容在代码的每个“步骤”上打印变量:
disp var
当我使用 pdb 调试 python 时,我想要类似的功能,但disp
似乎不存在,python pdb 文档似乎没有提供替代方案——但这似乎是一个奇怪的遗漏?
下面的代码使用 Python 自省功能向 PDB 模块添加两个新命令 0 只需将给定函数及其调用放在单独的模块中,并在开始调试之前导入此模块 - 你应该有 'disp' 和 'undisp'命令确实将手表添加和收回到变量。
它通过monkeypatching 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
不幸的是,我只能让它显示变量的状态,就像它们在执行最后一个命令之前一样。(我尝试了一点,但是对作为 Pdb 基础的 bdb 模块进行猴子补丁似乎也不起作用)。您可以尝试更改 pdb.Pdb、bdb.Bdb 或 cmd.Cmd 中修饰的方法,wrap
以找到在已调试帧状态更改后调用的方法。
您可以设置一些别名来为您执行此操作:
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
。