在调试期间更新函数(pdb 或 ipdb)



>想象一下,我正在调试以下脚本:

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)

相关内容

  • 没有找到相关文章

最新更新