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

时间:2018-01-05 11:01:15

标签: python debugging 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是否按预期运行。我看到那里有一个bug,所以我进入源代码并修复它。现在我想看看修复是否正确,但我不想再次运行脚本(因为它很慢),也不想将something_else保存在磁盘上(因为,也许,它非常大。)

有没有办法在调试器shell中更新fast_function()以便使用新的源代码?

3 个答案:

答案 0 :(得分:4)

您可以在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

答案 1 :(得分:3)

如果它是一个短函数,你可以在一个pdb行中覆盖现有函数。请注意,惊叹号在那里是可选的。

(pdb)...
(pdb)!def fast_function(something_else): print("Hello world");return True


如果函数的代码长度稍大,那么您可以利用普通的交互式shell(see this

(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&#39;建议我会更好。

请记住,每个pdb行都可以像执行一行普通的python代码一样工作,你可以动态地完成任何事情!在这个意义上,pdb比其他一些图形调试工具更强大。

P.S。似乎PyCharm确实支持根据ADR评估表达特征

答案 2 :(得分:2)

编辑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)