如何从PDB导出变量?

15
想象以下情景:从IPython shell启动脚本,在断点处调用Python调试器。使用PDB命令可以分析此时的代码和变量。但通常情况下,变量的值需要更深入的研究。
是否可能将变量的值导出到IPython shell中?
我的具体用例: 我正在处理一个非常庞大的NumPy数组,它似乎没有正确的值。我知道可以从Python调试器中运行任何Python命令,但保存不同断点处的变量值并在IPython shell中使用所有这些值会很有帮助。我想象中的解决方法是:
ipdb> global var1; var1 = var
ipdb> continue
...
ipdb> global var2; var2 = var
ipdb> continue
... 
In [2]: abs(var1 - var2) # do some interesting calculations with IPython

4个回答

16
您可以使用 globals():
ipdb>__name__
'my_module'
ipdb> get_var = 'a value'
ipdb> globals()['myvar'] = get_var
ipdb> q
In [11]: my_module.myvar
Out[11]: 'a value'

假设断点设置在my_module.py中,因此我们正在编辑模块my_module的全局变量。


1
这个不起作用,但我不确定为什么。我得到了“'myz'未定义”的错误。 - lumbric
@lumbric 你是如何运行它的? - chespinoza
1
我认为它没有起作用,因为myvar很可能存在于不同的模块中,而不是直接存在于IPython中。我编辑了你的回答以澄清这一点,请检查是否正确! - lumbric
不要使用globals(),而是可以导入任何模块,并将变量赋值给该模块中的字段。这对我来说更直观。 - John Lehmann
2
import sys, then sys.modules['__main__'].myvar = get_var - Brent Baccala

7

这并不是一个很好的解决方案,但已经可以工作了:

ipdb> import cPickle; f=open('/tmp/dump1','w+'); cPickle.dump(var,f); f.close()

...

ipdb> import cPickle; f=open('/tmp/dump2','w+'); cPickle.dump(var,f); f.close()

那么

In [2]: var1 = cPickle.load(open('/tmp/dump1'))
In [3]: var2 = cPickle.load(open('/tmp/dump2'))

5
你需要区分不同的globals()
例如,假设我们有一个模块:mymodule.py
foo = 100
def test():
    bar = 200
    return bar

我们在 pdb 控制下运行它。
>>> import pdb
>>> import mymodule
>>> foobar = 300
>>> pdb.run('mymodule.test()')
> <string>(1)<module>()
(Pdb) print foobar
300
(Pdb) print foo
*** NameError: name 'foo' is not defined
(Pdb) global foobar2; foobar2 = 301
(Pdb) print foobar2
301

在开始执行test()之前,pdb中的环境是当前的globals()。因此,foobar被定义了,而foo没有被定义。
然后我们执行test()并停留在bar = 200的结尾处。

-> bar = 200
(Pdb) print bar
200
(Pdb) print foo
100
(Pdb) print foobar
*** NameError: name 'foobar' is not defined
(Pdb) global foo2; foo2 = 101
(Pdb) print foo2
101
(Pdb) c
>>> 

pdb的环境已经改变。它在test()中使用mymoduleglobals()。因此,'foobar'未定义,而'foo'已定义。

我们导出了两个变量foobar2foo2,但它们存在不同的作用域。

>>> foobar2
301
>>> mymodule.foobar2

Traceback (most recent call last):
  File "<pyshell#16>", line 1, in <module>
    mymodule.foobar2
AttributeError: 'module' object has no attribute 'foobar2'
>>> mymodule.foo2
101
>>> foo2

Traceback (most recent call last):
  File "<pyshell#18>", line 1, in <module>
    foo2
NameError: name 'foo2' is not defined

你已经找到了解决方案。但它的工作方式略有不同。

1

根据上面的答案和评论,这对我来说是最直接的方法:

ipdb> import sys
ipdb> sys.abcdef = some_debugged_variable
ipdb> c

In [18]: import sys
In [19]: ipython_var = sys.abcdef

如果需要,您还可以在那里存储一个字典并保存多个命名对象。


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