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

Edg*_*rby 7 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()
Run Code Online (Sandbox Code Playgroud)

ipdb.set_trace()满足该行时,将提示调试器shell,现在我可以执行该final_output = fast_function(something_else)语句以检查是否fast_function按预期运行.我看到有一个bug,所以我进入源代码并修复它.现在我想看看修复是否正确但我不想第二次运行脚本(因为它很慢),也不想保存something_else在磁盘上(因为它可能非常大).

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

Leo*_*eon 6

您可以通过在 pdb 前面加上感叹号来在 pdb 中执行单行 python 语句。help execpdb 产生的as的输出如下:

(!) 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)
Run Code Online (Sandbox Code Playgroud)

使用此功能,您可以将函数的源代码保存在文件中,并在 pdb 中更新该函数,如下所示:

!exec(open("fast_function.py", "r").read())
Run Code Online (Sandbox Code Playgroud)

示范:

$ 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
Run Code Online (Sandbox Code Playgroud)