Python 程序员必知必会的开发者工具(3)

Python调试器与pdb模块

Python在pdb模块中包含了一个简单的基于命令行的调试器。pdb模块支持事后调试(post-mortem debugging),栈帧探查(inspection of stack frames),断点(breakpoints),单步调试(single-stepping of source lines)以及代码审查(code evaluation)。

有都能够在程序中调用调试器,或是在交互式的Python终端中进行调试工作。

在所有启动调试器的函数中,函数set_trace()也许是最简易实用的了。如果在复杂程序中发现了问题,可以在代码中插入set_trace()函数,并运行程序。当执行到set_trace()函数时,这就会暂停程序的执行并直接跳转到调试器中,这时候你就可以大展手脚开始检查运行时环境了。当退出调试器时,调试器会自动恢复程序的执行。

假设你的程序有问题,你想找到一个简单的方法来对它进行调试。

如果你的程序崩溃时报了一个异常错误,那么你可以用python3 -i someprogram.py这个命令来运行你的程序,这能够很好地发现问题所在。-i选项表明只要程序终结就立即启动一个交互式shell。在这个交互式shell中,你就可以很好地探查到底发生了什么导致程序的错误。例如,如果你有以下代码:

def function(n):
    return n + 10

function("Hello")

如果使用python3 -i 命令运行程序就会产生如下输出:

python3 -i sample.py
Traceback (most recent call last):
  File "sample.py", line 4, in <module>
    function("Hello")
  File "sample.py", line 2, in function
    return n + 10
TypeError: Can&#039;t convert &#039;int&#039; object to str implicitly
>>> function(20)
30
>>>

如果你没有发现什么明显的错误,那么你可以进一步地启动Python调试器。例如:

>>> import pdb
>>> pdb.pm()
> sample.py(4)func()
-> return n + 10
(Pdb) w
sample.py(6)<module>()
-> func(&#039;Hello&#039;)
> sample.py(4)func()
-> return n + 10
(Pdb) print n
&#039;Hello&#039;
(Pdb) q
>>>

如果你的代码身处的环境很难启动一个交互式shell的话(比如在服务器环境下),你可以增加错误处理的代码,并自己输出跟踪信息。例如:

import traceback
import sys
try:
    func(arg)
except:
    print(&#039;**** AN ERROR OCCURRED ****&#039;)
    traceback.print_exc(file=sys.stderr)

如果你的程序并没有崩溃,而是说程序的行为与你的预期表现的不一致,那么你可以尝试在一些可能出错的地方加入print()函数。如果你打算采用这种方案的话,那么还有些相关的技巧值得探究。首先,函数traceback.print_stack()能够在被执行时立即打印出程序中栈的跟踪信息。例如:

>>> def sample(n):
...    if n > 0:
...        sample(n-1)
...    else:
...        traceback.print_stack(file=sys.stderr)
...
>>> sample(5)
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in sample
File "<stdin>", line 3, in sample
File "<stdin>", line 3, in sample
File "<stdin>", line 3, in sample
File "<stdin>", line 3, in sample
File "<stdin>", line 5, in sample
>>>

另外,你可以在程序中任意一处使用pdb.set_trace()手动地启动调试器,就像这样:

import pdb
def func(arg):
    ...
    pdb.set_trace()
    ...

在深入解析大型程序的时候,这是一个非常实用的技巧,这样操作能够清楚地了解程序的控制流或是函数的参数。比如,一旦调试器启动了之后,你就可以使用print或者w命令来查看变量,来了解栈的跟踪信息。

在进行软件调试时,千万不要让事情变得很复杂。有时候仅仅需要知道程序的跟踪信息就能够解决大部分的简单错误(比如,实际的错误总是显示在跟踪信息的最后一行)。在实际的开发过程中,将print()函数插入到代码中也能够很方便地显示调试信息(只需要记得在调试完以后将print语句删除掉就行了)。调试器的通用用法是在崩溃的函数中探查变量的值,知道如何在程序崩溃以后再进入到调试器中就显得非常实用。在程序的控制流不是那么清楚的情况下,你可以插入pdb.set_trace()语句来理清复杂程序的思路。本质上,程序会一直执行直到遇到set_trace()调用,之后程序就会立刻跳转进入到调试器中。在调试器里,你就可以进行更多的尝试。如果你正在使用Python的IDE,那么IDE通常会提供基于pdb的调试接口,你可以查阅IDE的相关文档来获取更多的信息。

下面是一些Python调试器入门的资源列表:

阅读Steve Ferb的文章 &#8220;Debugging in Python&#8221;

观看Eric Holscher的截图 &#8220;Using pdb, the Python Debugger&#8221;

阅读Ayman Hourieh的文章 &#8220;Python Debugging Techniques&#8221;

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/aea16bd1eb722abb06eeb8676a84074c.html