>想象一下,我正在调试以下脚本:
import ipdb
def slow_function(something):
# I'm a very slow function
return something_else
def fast_function(something_else):
# There's a bug here
return final_output
something = 1
something_else = slow_function(something)
ipdb.set_trace()
final_output = fast_function(something_else)
ipdb.set_trace()
当满足ipdb.set_trace()
行时,将提示调试器 shell,我现在可以执行 final_output = fast_function(something_else)
语句来检查fast_function
是否按预期运行。我看到有一个错误,所以我进入源代码并修复它。现在我想看看修复是否正确,但我不想第二次运行脚本(因为它很慢(,也不想something_else
保存在磁盘上(因为,也许,它非常大(。
有没有办法在调试器 shell 中更新 fast_function(( 以便使用新的源代码?
您可以在 pdb 中执行单行 python 语句,方法是在它前面加上感叹号。由 pdb 生成的help exec
输出如下:
(!) statement
Execute the (one-line) statement in the context of the current
stack frame. The exclamation point can be omitted unless the
first word of the statement resembles a debugger command. To
assign to a global variable you must always prefix the command
with a 'global' command, e.g.:
(Pdb) global list_options; list_options = ['-l']
(Pdb)
使用此工具,您可以将函数的源代码保存在文件中,并在 pdb 中更新该函数,如下所示:
!exec(open("fast_function.py", "r").read())
示范:
$ cat test.py
import pdb;
def foo():
print('Foo');
foo()
pdb.set_trace()
foo()
$ python3 test.py
Foo
> test.py(8)<module>()
-> foo()
(Pdb) cont
Foo
$ cat foo.py
def foo():
print('Modified Foo');
$ python3 test.py
Foo
> test.py(8)<module>()
-> foo()
(Pdb) !exec(open("foo.py", "r").read())
(Pdb) cont
Modified Foo
如果它是一个短函数,你可以在一个 pdb 行中覆盖现有函数。请注意,感叹号在那里是可选的。
(pdb)...
(pdb)!def fast_function(something_else): print("Hello world");return True
如果函数的代码长度稍大,那么你可以利用普通的交互式shell(见这个(
(Pdb) !import code; code.interact(local=vars())
(InteractiveConsole)
In : def fast_function(something_else):
...: print 'hello in pdb'
...:
In : # use ctrl+d here to return to pdb shell...
(Pdb) !fast_function(arg)
hello in pdb
如果函数的代码也不容易用交互式shell管理,我想Leons的建议会更好。
请记住,每个 pdb 行都可以像执行一行普通的 python 代码一样工作,并且您几乎可以即时实现任何事情! 从这个意义上说,PDB 比其他一些图形调试工具更强大。
P.S. 似乎 PyCharm 确实支持根据 ADR 评估表达式特征
编辑19/01/2018
您可以将结果写入内存上的文件。 例如/dev/shm 是一个 tmpfs 分区。 大小可以使用协议转储的KeyArgs进行优化。
# save result
with open('/dev/shm/data.pk', 'w' ) as data:
pickle.dump(something_else, data, protocole=3)
第一次可以使用 pickle 将结果存储在文件中,然后重新加载以调试第二个函数
import pickle
def slow_function(something):
# I'm a very slow function
return something + 42
def fast_function(something_else):
# There's a bug here
return something_else + 42
something = 1
something_else = slow_function(something)
# save result
with open('data.pk', 'w' ) as data:
pickle.dump(something_else, data)
第二次发射
import ipdb
# load result from disk
with open('data.pk', 'r' ) as data:
something_else = pickle.load(data)
ipdb.set_trace()
fast_function(something_else)