2011-10-05 84 views
36

我正在调试一个python脚本,我想观察一个变量的变化(就像你可以在gdb中看内存地址一样)。有没有办法做到这一点?你如何看pdb中的变量

+0

您可以在[pudb](https://pypi.python.org/pypi/pudb) –

+0

@WayneWerner小心地添加一个显示此链接或链接到文档的答案?我正在明确寻找如何在'pudb'中做到这一点,但是会出现空...... –

+0

@JeffWidman这将是另一个问题 - 当你问我时,让我知道:) –

回答

22

这是一个非常冒险的方式来与pdb做到这一点。这些命令可以放在您的~/.pdbrc中,每次使用pdb时自动加载。

!global __currentframe, __stack; from inspect import currentframe as __currentframe, stack as __stack 
!global __copy; from copy import copy as __copy 
!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 _setup_watchpoint !global __key, __dict, __val; __key = '%1'; __dict = __currentframe().f_locals if __currentframe().f_locals.has_key(__key) else __currentframe().f_globals; __val = __copy(%1) 

alias _nextwatch_internal next;; !if __dict[__key] == __val: __pdb.cmdqueue.append("_nextwatch_internal %1") 
alias _stepwatch_internal step;; !if __dict[__key] == __val: __pdb.cmdqueue.append("_stepwatch_internal %1") 

alias nextwatch __pdb.cmdqueue.extend(["_setup_watchpoint %1", "_nextwatch_internal"]) 
alias stepwatch __pdb.cmdqueue.extend(["_setup_watchpoint %1", "_stepwatch_internal"]) 

这增加了两个命令,nextwatchstepwatch其中每个取变量名VARNAME作为参数。如果可能的话,他们将为varname制作当前帧的局部变量的浅拷贝,并分别继续执行nextstep,直到该名称指向更改的名称。

这适用于CPython 2.7.2,但依赖于一些pdb内部,因此它可能会在其他地方打破。

+0

我将宏复制到我的〜/ .pdbrc文件中。然而pdb告诉我:NameError'nextwatch'未定义。我倒是这样的:“nextwatch”(var) –

+0

我使用python 3.5,mac,似乎'.pdbrc'不工作,即使当我把上面的代码粘贴到'(pdb):'环境中,当我运行'stepwatch'或者'nextwatch',它说'__dict'和其他的没有定义。你能更新python 3.5的代码吗?谢谢 – Daniel

+0

如上所述,这可能在其他一些Python版本中不起作用。发布一个Python 3.5版本作为新的答案 –

16

如果您在点击断点时收看变量,可以使用commands命令。例如。当打断点#1(canonical example from pdb doc)时打印some_variable

(Pdb) commands 1 
(com) print some_variable 
(com) end 
(Pdb) 
+0

这应该是最好的答案,简单,直接,教你一个pdb的简洁功能 - 断点命令 –

+1

尽管它很有用,但它并不直接回答问题,它希望监视变量的变化,然后在这些变化中断开,而不仅仅是在预设的断点处查看变量的状态。 – kmantel

8

对于Python 3中

可以使用PDB

display功能一旦命中断点只需输入

IPDB>显示表达

例如:

ipdb> display instance 
display instance: <AppUser: dmitry4> 
ipdb> display instance.id 
display instance.id: 9 
ipdb> display instance.university 
display instance.university: <University: @domain.com> 

ipdb> display 

Currently displaying: 
instance.university: <University: @domain.com> 
instance.id: 9 
instance: <AppUser: dmitry4> 
ipdb> 

,你可以看到,每次键入显示 - 这将打印所有手表(表情)的。您可以使用未显示功能来删除某些手表。

您还可以使用PP表达到prettyprint表达(非常有用)

6

一个可能的解决方案是使用pdb++

pip install pdbpp 

然后“标记”您想观看的对象装饰者@pdb.break_on_setattr

from pdb import break_on_setattr 
@break_on_setattr('bar') 
class Foo(object): 
    pass 

f = Foo() 
f.bar = 42 # the program breaks here 

这里pdb wil l在任何Foo对象上打破属性bar的任何更改。

注意事项
只有底层__setattr__ - 方法的调用将触发断点。这意味着f.bar = 'XYZ'setattr(f, 'XYZ')会工作,但操纵bar -object不会触发断点:

f.bar = [] 
f.bar.append(7) # will NOT trigger breakpoint 

f.bar = 2 
f.bar += 5  # will trigger breakpoint 

注:@break_on_setattr不是标准pdb -module的一部分。 pdbpdbpp -package覆盖/猴子修补。