【问题标题】:Python debugger: Stepping into a function that you have called interactivelyPython 调试器:步入您以交互方式调用的函数
【发布时间】:2010-09-18 17:21:22
【问题描述】:

Python 很酷,但不幸的是,它的调试器不如 perl -d。

我在试验代码时经常做的一件事是从调试器中调用一个函数,然后单步执行该函数,如下所示:

# NOTE THAT THIS PROGRAM EXITS IMMEDIATELY WITHOUT CALLING FOO()
~> cat -n /tmp/show_perl.pl
1  #!/usr/local/bin/perl
2
3  sub foo {
4      print "hi\n";
5      print "bye\n";
6  }
7
8  exit 0;

~> perl -d /tmp/show_perl.pl

Loading DB routines from perl5db.pl version 1.28
Editor support available.

Enter h or `h h' for help, or `man perldebug' for more help.

main::(/tmp/show_perl.pl:8):    exit 0;

# MAGIC HAPPENS HERE -- I AM STEPPING INTO A FUNCTION THAT I AM CALLING INTERACTIVELY
  DB<1> s foo() 
main::((eval 6)[/usr/local/lib/perl5/5.8.6/perl5db.pl:628]:3):
3:      foo();


  DB<<2>> s
main::foo(/tmp/show_perl.pl:4):     print "hi\n";


  DB<<2>> n
hi
main::foo(/tmp/show_perl.pl:5):     print "bye\n";


  DB<<2>> n
bye


  DB<2> n
Debugged program terminated.  Use q to quit or R to restart,
  use O inhibit_exit to avoid stopping after program termination,
  h q, h R or h O to get additional info.  

  DB<2> q

这在尝试单步执行函数对各种不同输入的处理以找出失败的原因时非常有用。但是,它似乎在 pdb 或 pydb 中都不起作用(我将展示与上述示例等效的 python 示例,但它会导致大量异常堆栈转储)。

所以我的问题是双重的:

  1. 我错过了什么吗?
  2. 是否有 python 调试器确实可以让我这样做?

显然我可以自己将调用放入代码中,但我喜欢交互式工作,例如。当我想尝试使用稍微不同的一组参数进行调用时,不必从头开始。

【问题讨论】:

标签: python debugging pdb


【解决方案1】:

如果您更熟悉 GUI 调试器,则可以使用 winpdb(在这种情况下,“win”不是指 Windows)。我实际上在 Linux 上使用它。

在 debian/ubuntu 上:

sudo aptitude install winpdb

然后把它放在你想要中断的代码中:

import rpdb2; rpdb2.start_embedded_debugger_interactive_password()

然后启动 winpdb 并附加到您的运行脚本。

【讨论】:

【解决方案2】:

您也可以使用 pdb 交互式调试函数,前提是您要调试的脚本最后没有 exit():

$ cat test.py
#!/usr/bin/python

def foo(f, g):
        h = f+g
        print h
        return 2*f

要调试,请启动交互式 python 会话并导入 pdb:

$ python
Python 2.5.1 (r251:54869, Apr 18 2007, 22:08:04) 
[GCC 4.0.1 (Apple Computer, Inc. build 5367)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import pdb
>>> import test
>>> pdb.runcall(test.foo, 1, 2)
> /Users/simon/Desktop/test.py(4)foo()
-> h = f+g
(Pdb) n
> /Users/simon/Desktop/test.py(5)foo()
-> print h
(Pdb) 

pdb 模块随 python 一起提供,并记录在模块文档中http://docs.python.org/modindex.html

【讨论】:

  • pdb.run 或 pdb.runeval 将停在代码的第一行,而 pdb.runcall 不会,这可能只是在调试中返回错误,我们需要 %debug 来检查事后而不是想要的一步一步。
【解决方案3】:

对于我正在开发的代码的交互工作,我通常发现使用pdb.set_trace 在代码本身中设置程序化“断点”更有效。这也使得在循环深处中断程序状态变得更容易:if &lt;state&gt;: pdb.set_trace()

【解决方案4】:

有一个 python 调试器是 python 核心发行版的一部分,称为“pdb”。我自己很少使用它,但有时觉得它很有用。

鉴于这个程序:

def foo():
    a = 0
    print "hi"

    a += 1

    print "bye"

foo()

这是一个调试它的会话:

$ python /usr/lib/python2.5/pdb.py /var/tmp/pdbtest.py         ~
> /var/tmp/pdbtest.py(2)<module>()
-> def foo():
(Pdb) s
> /var/tmp/pdbtest.py(10)<module>()
-> foo()
(Pdb) s
--Call--
> /var/tmp/pdbtest.py(2)foo()
-> def foo():
(Pdb) s
> /var/tmp/pdbtest.py(3)foo()
-> a = 0
(Pdb) s
> /var/tmp/pdbtest.py(4)foo()
-> print "hi"
(Pdb) print a
0
(Pdb) s
hi
> /var/tmp/pdbtest.py(6)foo()
-> a += 1
(Pdb) s
> /var/tmp/pdbtest.py(8)foo()
-> print "bye"
(Pdb) print a
1
(Pdb) s
bye
--Return--
> /var/tmp/pdbtest.py(8)foo()->None
-> print "bye"
(Pdb) s
--Return--
> /var/tmp/pdbtest.py(10)<module>()->None
-> foo()
(Pdb) s

【讨论】:

    【解决方案5】:

    我已经回答了我自己的问题!这是pydb中的“调试”命令:

    ~> cat -n /tmp/test_python.py
         1  #!/usr/local/bin/python
         2
         3  def foo():
         4      print "hi"
         5      print "bye"
         6
         7  exit(0)
         8
    
    ~> pydb /tmp/test_python.py
    (/tmp/test_python.py:7):  <module>
    7 exit(0)
    
    
    (Pydb) debug foo()
    ENTERING RECURSIVE DEBUGGER
    ------------------------Call level 11
    (/tmp/test_python.py:3):  foo
    3 def foo():
    
    ((Pydb)) s
    (/tmp/test_python.py:4):  foo
    4     print "hi"
    
    ((Pydb)) s
    hi
    (/tmp/test_python.py:5):  foo
    5     print "bye"
    
    
    ((Pydb)) s
    bye
    ------------------------Return from level 11 (<type 'NoneType'>)
    ----------------------Return from level 10 (<type 'NoneType'>)
    LEAVING RECURSIVE DEBUGGER
    (/tmp/test_python.py:7):  <module>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-19
      相关资源
      最近更新 更多