学习
实践
活动
工具
TVP
写文章

使用pdb进行Python调试

显示表达式

与使用p和pp打印表达式类似,你可以使用命令display [expression]告诉pdb自动显示表达式的值,如果它改变,执行停止。使用命令undisplay [expression]来清除显示表达式。

以下是这两个命令的语法和描述:

下面是example4display.py的一个例子,演示了它在循环中的使用:

在上面的输出中,pdb自动显示char变量的值,因为每次命中断点时,其值都发生了变化。有时这是有用的,正是你想要的,但还有另一种使用display的方式。

你可以多次输入display来构建表达式的观察列表。这比用p更容易。添加完所有感兴趣的表达式后,只需输入display查看当前值即可:

Python调用者ID

最后这一节我们将建立在目前所了解的内容上。我参考电话系统的来电者识别功能使用“调用者ID”这一称呼。这正是这个例子演示的内容,除了它适用于Python。

以下是主脚本example5.py的源代码:

以下是实用程序模块fileutil.py:

在这种情况下,想象在实用程序模块get_path()中有一个带有函数的大型代码库,该函数被无效输入调用。但是它是从不同包中的不同地方被调用的。

你如何找到调用者是谁?

使用命令w(where)打印堆栈跟踪,最近一帧在底部:

如果这看起来让你困惑或者你不确定堆栈跟踪或帧是什么,请不要担心。我将在下面解释这些术语。它们并不像听起来那么难。

由于最近帧在底部,所以从那里开始并从底部向上阅读。查看以 - >开头的行,但跳过第一个实例,因为这是在函数get_path()中使用pdb.set_trace()进入pdb的地方。在这个例子中,调用函数get_path()的代码行是:

每个 - >上方的行包含文件名,行号(括号中)以及源代码行所在的函数名称。因此调用者是:

在这个小示例中,为了演示的目的,这并不奇怪,但想象一个大型应用程序,你可以在其中设置一个带条件的断点以标识输入值发生错误的位置。

现在我们知道了如何找到调用者。

那么堆栈跟踪和帧呢?

堆栈跟踪只是Python为创建跟踪函数调用而创建的所有帧的列表。帧是Python在调用函数时创建的数据结构,在返回时即删除。堆栈只是在任何时间点有序的帧或函数调用列表。(函数调用)堆栈在应用程序的整个生命周期中随着函数的调用而增长和缩小,然后返回。

打印时,这个有序的帧列表,也即堆栈,被称为堆栈跟踪。你随时可以通过输入命令w来查看它,就像我们在上面找到调用者一样。

| 有关详细信息,请参阅Wikipedia上调用堆栈的文章。

为了更好地理解pdb,让我们仔细看看w的帮助:

“当前帧”是什么意思?

将当前帧视为pdb已停止执行的当前函数。换句话说,当前帧是你的程序当前暂停的位置,并用作p(print)命令的参照系。

当需要时,p和其他命令将使用当前帧作为上下文。在命令p的情况下,当前帧将用于查找和打印变量引用。

当pdb打印堆栈跟踪时,箭头>表示当前帧。

这有用吗?

你可以使用两个命令u(up)和d(down)来更改当前帧。与p结合使用,你可以在任何帧的调用堆栈中的任意点检查程序中的变量和状态。

以下是这两个命令的语法和描述:

我们来看一个使用u和d命令的例子。在这种情况下,我们要检查example5.py中函数get_file_info()的局部变量full_fname。为了做到这一点,我们必须使用命令u将当前帧提升一个级别:

调用pdb.set_trace()是在fileutil.py中的get_path()函数中,所以当前帧最初设置在那。你可以在上面的第一行输出中看到它:

要访问和打印example5.py中的函数get_file_info()里的局部变量full_fname,使用命令u向上移动一个级别:

注意在上面的u的输出中,pdb在第一行的开始处输出了箭头>。这是pdb让你知道帧被改变了,这个源位置现在是当前帧。现在可以访问变量full_fname。另外,重要的是要实现以第二行上的 - >开始的代码行。由于帧被移到堆栈上,所以调用了fileutil.get_path()。使用u,我们将堆栈(从某种意义上来说)移动到调用fileutil.get_path()的函数example5.get_file_info()中。

继续这个例子,在打印完full_fname之后,当前帧使用d移动到其原始位置,并且打印了get_path()中的局部变量fname。

如果我们想,我们可以通过将计数参数传递给u或d来一次移动多个帧。例如,我们可以通过输入u 2来移动到example5.py中的模块级别:

在调试和思考许多不同的事情时,很容易忘记程序执行到哪一步。请记住,你始终可以使用恰当的命令w(where)来查看执行暂停的位置以及当前帧的位置。

pdb基本命令

一旦你使用pdb一段时间,你会发现要了解全部知识还有很长的路要走。你始终可以通过h命令获得帮助。

只需输入h或help获取所有命令的列表或帮助你完成特定的命令或。

为了快速参考,这里列出了一些重要的命令:

使用pdb进行Python调试:结论

在本教程中,我们介绍了pdb的一些基本和常见用法:

打印表达式

使用n(next)和s(step)单步执行代码

使用断点

使用unt(until)继续执行

显示表达式

找到函数的调用者

希望这对你有所帮助。如果你想了解更多信息,请参阅:

在pdb提示符下输入(Pdb)h pdb获取pdb的完整文档

Python的pdb文档

示例中使用的源代码可以在关联的GitHub存储库中找到。 请务必查看我们可打印的pdb命令参考,你可以在调试时将其用作备忘手册。

此外,如果你想学习使用基于GUI的Python调试器,请阅读我们的Python IDE和编辑指南,了解哪些选择最适合你。祝Python编程愉快!

英文原文:https://realpython.com/python-debugging-pdb/

译者:β

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180503A07X6K00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码关注腾讯云开发者

领取腾讯云代金券