如何从PDB导出变量?
想象一下这样的场景:你在IPython的命令行中启动了一个脚本,然后在某个断点时调用了Python的调试器。通过使用调试器的命令,你可以分析此时的代码和变量。但是,很多时候你会发现变量的值需要更深入的研究。
那么,有没有办法把一个变量的值导出到IPython的命令行呢?
我具体的需求是:我正在处理一个相当大的numpy数组,但它似乎没有正确的值。我知道我可以在调试器中运行任何Python命令,但如果能在不同的断点保存变量的值,并在IPython命令行中使用这些值,那就太好了。我想象的效果是这样的:
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 个回答
6
你需要区分不同的 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()
中的 mymodule
的 globals()
。因此,foobar
现在没有定义,而 foo
是定义过的。
我们已经导出了两个变量 foobar2
和 foo2
,但是它们存在于不同的作用域中。
>>> 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
你已经找到了解决方案。不过它的工作方式稍微有点不同。
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'))
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
这个模块的全局变量。