暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Python调试器:pdb

一只大鸽子 2023-02-21
493

为什么用pdb

pdb(Python Debugger)
是Python内置的交互式调试器,可以检查程序的状态,打印变量,逐语句查看Python程序。

写代码避免不了出bug对于简单的问题可以使用print
函数帮助定位错误。但如果问题比较复杂时,一行行print
就比较麻烦了。如果有PyCharm
等工具,可以利用其调试功能。但有些情况只能使用命令行(例如远程服务器),pdb
就是一个很好的调试工具。

C语言程序使用gdb调试,pdb用法和gdb用法非常相似[1]。

使用pdb

要启动调试器,只需要在断点处添加breakpoint()
函数。

注:Python3.7 版本后支持breakpoint()函数。之前版本可以用import pdb; pdb.set_trace()

# main.py
def div_it(i):
    a = 100
    breakpoint()
    print(a/i)

 
lst = [1,2,3,0,5]
for x in lst:
    div_it(x)

之后我们正常运行程序:python main.py
, 执行到breakpoint()
时,程序就会在这行代码前暂停执行。启动程序的终端变成了一个交互式Python shell。

> python main.py
> d:\test\gdb_test\main.py(5)div_it()
-> print(a/i)
(Pdb)

(Pdb)
提示符下,你可以键入局部变量的名称(或者使用p <name>
),以看到它们的值被打印出来。你可以通过调用locals()
内置函数看到所有局部变量的列表。你可以导入模块,检查全局状态,构造新的对象,运行帮助内置函数,甚至修改正在运行的程序的一部分--无论你需要做什么来帮助你的调试。

(Pdb) x
1
(Pdb) locals()
{'i'1'a'100}

此外,调试器还有各种命令来控制和理解程序的执行,输入help
可以看到完整的列表。下面是3个常用命令:

where
:打印当前执行的调用堆栈。这可以让你弄清楚你在程序中的位置以及你是如何到达断点触发点的。 
up
:将你的范围从执行调用栈上移到当前函数的调用者。这可以让你检查导致断点的更高层次的程序中的局部变量。 
down
:将你的范围从执行调用堆栈下移一级。

当你完成对当前状态的检查后,你可以使用这5个调试器命令以不同的方式控制程序的执行。
step
:运行程序直到程序中的下一行执行。如果下一行的执行包括调用一个函数,调试器会在被调用的函数内停止。 
next
:运行程序直到当前函数中的下一行执行。如果下一行的执行包括调用一个函数,调试器将不会在被调用的函数返回之前停止。 
return
:运行程序直到当前函数返回,然后将控制权返回到调试器提示符。 
continue
:继续运行程序,直到碰到下一个断点(通过调用断点或由调试器命令添加的断点)。 
quit
:退出调试器并结束程序。如果你已经发现了问题,走得太远,或者需要对程序进行修改,再试一次,请运行此命令。

post-mortem 事后分析

另一个使用调试器的有用方法是使用post-mortem
调试。这使你能够在程序已经引发异常和崩溃之后再进行调试。当你不太确定该把breakpoint()
函数调用放在哪里时,这尤其有帮助。

# main.py
def div_it(i):
    a = 100
    print(a/i)

 
lst = [1,2,3,0,5]
for x in lst:
    div_it(x)

我使用命令行python -m pdb -c continue main.py
来在pdb模块的控制下运行程序。continue
命令告诉pdb立即启动程序。一旦运行,程序遇到问题就会自动进入交互式调试器,这时我可以检查程序的状态

> python -m pdb -c continue main.py
100.0
50.0
33.333333333333336
Traceback (most recent call last):
  File "D:\anocda\lib\pdb.py", line 1701in main
    pdb._runscript(mainpyfile)
  ...
    def div_it(i):
  File "d:\test\gdb_test\main.py", line 4in div_it
    print(a/i)
ZeroDivisionError: division by zero
Uncaught exception. Entering post mortem debugging
Running 'cont' or 'step' will restart the program
> d:\test\gdb_test\main.py(4)div_it()
-> print(a/i)

在交互式Python解释器中遇到未捕获的异常后,也可以通过调用pdb模块的pm函数pdb.pm()
使用post-mortem调试。

> python
>>> import main
100.0
50.0
33.333333333333336
Traceback (most recent call last):
  File "<stdin>", line 1in <module>
  File "D:\TEST\gdb_test\main.py", line 9in <module>
    div_it(x)
  File "D:\TEST\gdb_test\main.py", line 4in div_it
    print(a/i)
ZeroDivisionError: division by zero
>>> import pdb; pdb.pm()
> d:\test\gdb_test\main.py(4)div_it()
-> print(a/i)
(Pdb) i
0
(Pdb)

参考

[1]pdb简介:http://c.biancheng.net/view/8153.html
[2]官网文档pdb --- Python 的调试器:https://docs.python.org/zh-cn/3/library/pdb.html?highlight=pdb
[3]《Effecitive Python 第二版》Item 80:考虑用pdb进行交互式调试


文章转载自一只大鸽子,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论