📜  使用 Pdb 在Python调试

📅  最后修改于: 2022-05-13 01:54:33.161000             🧑  作者: Mango

使用 Pdb 在Python调试

Python的 PDB 模块为我们提供了引人注目的Python代码调试的巨大亮点。这包括:

  • 程序的暂停
  • 查看每一行代码的执行情况
  • 检查变量的值

这个模块已经安装了Python。因此,我们只需要将其导入到我们的代码中即可使用其功能。在此之前,我们必须了解下面提到的一些概念:

  1. 要导入,我们只需在代码中使用import pdb即可。
  2. 为了调试,我们将使用pdb.set_trace()方法。现在,在Python 3.7 中, breakpoint()方法也可用于此目的。
  3. 我们在Python idle 终端上运行它(您可以使用任何 ide 终端来运行)。

让我们从一个由几行代码组成的简单示例开始。

例子:

Python3
# importing pdb
import pdb
  
# make a simple function to debugg
def fxn(n):
    for i in range(n):
        print("Hello! ", i+1)
  
  
# starting point to debugg
pdb.set_trace()
fxn(5)


Python3
# a simple function
def fxn(n):
    for i in range(n):
        print("Hello! ", i+1)
  
  
# using breakpoint
breakpoint()
fxn(5)


Python3
# importing pdb
import pdb
  
# define recursive function
def rec_fxn(r):
    if r > 0:
  
        # set trace
        pdb.set_trace()
        rec_fxn(r//2)
    else:
        print("recursion stops")
    return
  
# set trace at start
pdb.set_trace()
rec_fxn(5)


Python3
# importing pdb
import pdb
  
# simple function
def fxn(n):
    l=[]
    for i in range(n):
        l.append(i)
  
    # set trace
    pdb.set_trace()
    return
  
fxn(5)


Python3
# importing pdb
import pdb
  
# simple function
def fxn(n):
    l = []
    for i in range(n):
        l.append(i)
    return
  
  
# set trace
pdb.set_trace()
fxn(5)


Python3
# importing pdb
import pdb
  
# simple function
def fxn(n):
    l = []
      
    for i in range(n):
        l.append(i)
    print(l)
    return
  
  
# set trace
pdb.set_trace()
fxn(5)


Python3
# importing pdb
import pdb
  
# simple function
def fxn(n):
    
    # set trace
    pdb.set_trace()
    l = []
      
    for i in range(n):
        l.append(i)
    print(l)
    return
  
  
fxn(5)


Python3
# importing pdb
import pdb
  
# simple function
def fxn(n):
    l=[]
  
    for i in range(n):
        l.append(i)
    return
  
# set trace
pdb.set_trace()
fxn(5)


Python3
# importing pdb
import pdb
  
# simple function
def fxn(n):
    l = []
      
    for i in range(n):
        l.append(i)
      
    # set trace
    pdb.set_trace()
    print(l)
    return
  
  
fxn(5)


Python3
# importing pdb
import pdb
  
# simple function
def fxn(i):
    print(i)
    return
  
# set trace
pdb.set_trace()
for i in range(5):
    fxn(i)


输出:

在这里,我们可以看到,当函数调用完成时,pdb 会执行并请求下一个命令。我们可以在这里使用一些命令,例如

要了解有关不同命令的更多信息,您可以键入 help 并获取所需信息。



现在,我们将在 n 命令的帮助下进一步执行我们的程序。

以类似的方式,我们可以使用 breakpoint() 方法(不需要导入 pdb)。

蟒蛇3

# a simple function
def fxn(n):
    for i in range(n):
        print("Hello! ", i+1)
  
  
# using breakpoint
breakpoint()
fxn(5)

输出:

PDB 调试提供的功能

1. 打印变量或表达式

在使用打印顺序 p 时,您传递了一个由Python评估的清晰度。如果您传递变量名,pdb 会打印其当前值。尽管如此,您还可以做更多的事情来检查正在运行的应用程序的状况。

PDB调试在递归检查变量中的应用



在这个例子中,我们将定义一个带有 pdb trace 的递归函数,并在每次递归调用时检查变量的值。为了打印变量的值,我们将使用一个带有变量名称的简单打印关键字。

蟒蛇3

# importing pdb
import pdb
  
# define recursive function
def rec_fxn(r):
    if r > 0:
  
        # set trace
        pdb.set_trace()
        rec_fxn(r//2)
    else:
        print("recursion stops")
    return
  
# set trace at start
pdb.set_trace()
rec_fxn(5)

输出:

检查表达式的示例

这个例子类似于上面的例子,它在计算后打印表达式的值。

蟒蛇3

# importing pdb
import pdb
  
# simple function
def fxn(n):
    l=[]
    for i in range(n):
        l.append(i)
  
    # set trace
    pdb.set_trace()
    return
  
fxn(5)

输出:

2. 逐步移入代码



这是 pdb 提供的最重要的特性。为此使用了两个主要命令,如下所示:

让我们通过一个例子来理解这些的工作原理。

蟒蛇3

# importing pdb
import pdb
  
# simple function
def fxn(n):
    l = []
    for i in range(n):
        l.append(i)
    return
  
  
# set trace
pdb.set_trace()
fxn(5)

使用 n 输出:

使用 s 输出:

3. 使用断点



此功能帮助我们在源代码中的特定行动态创建断点。在这里,在这个例子中,我们使用下面给出的命令 b 创建断点:

b(reak) [ ([filename:]lineno | function) [, condition] ]
        Without argument, list all breaks.

使用行号参数,在当前文件的这一行设置一个中断。与函数名称,设置在该函数的第一个可执行线路断路。如果存在第二个参数,则它是一个字符串,指定一个表达式,该表达式必须在断点生效之前计算为真。

行号可能以文件名和冒号为前缀,以指定另一个文件(可能尚未加载的文件)中的断点。在 sys.path 上搜索文件; .py 后缀可以省略。

蟒蛇3

# importing pdb
import pdb
  
# simple function
def fxn(n):
    l = []
      
    for i in range(n):
        l.append(i)
    print(l)
    return
  
  
# set trace
pdb.set_trace()
fxn(5)

输出:

4. 执行代码直到指定行

使用 unt 像 c 一样继续执行,但是,在比当前行更值得注意的下一行停止。有时,unt 会更有帮助且使用起来更快,而且实际上正是您所需要的。

unt(il) [lineno]

不带参数,继续执行,直到到达编号大于当前编号的行。使用行号,继续执行,直到到达编号大于或等于该行的行。在这两种情况下,也在当前帧返回时停止。

蟒蛇3



# importing pdb
import pdb
  
# simple function
def fxn(n):
    
    # set trace
    pdb.set_trace()
    l = []
      
    for i in range(n):
        l.append(i)
    print(l)
    return
  
  
fxn(5)

输出:

5. 列出代码

Listing Source code 是另一个功能,可用于跟踪带有行号作为列表的代码。为此使用 ll 命令。

让我们通过一个例子来理解 longlist 的工作原理。

蟒蛇3

# importing pdb
import pdb
  
# simple function
def fxn(n):
    l=[]
  
    for i in range(n):
        l.append(i)
    return
  
# set trace
pdb.set_trace()
fxn(5)

输出:

6. 显示表达式



就像用 p 和 pp 打印关节一样,您可以使用命令 show [expression] 来建议 pdb 因此显示关节的估计,如果它发生变化,当执行停止时。使用命令 undisplay [expression] 清除展示表达。

display [expression]

如果表达式的值发生变化,则显示表达式的值,每次在当前帧中停止执行。不带表达式,列出当前帧的所有显示表达式。

undisplay [expression]

不再在当前帧中显示表达式。不带表达式,清除当前帧的所有显示表达式。

蟒蛇3

# importing pdb
import pdb
  
# simple function
def fxn(n):
    l = []
      
    for i in range(n):
        l.append(i)
      
    # set trace
    pdb.set_trace()
    print(l)
    return
  
  
fxn(5)

输出:

7.上下帧

在这里,我们可以将每条轨迹作为一帧进行播放,也可以从一帧移动到另一帧。

w(here)

打印堆栈跟踪,最新的帧在底部。箭头表示“当前帧”,它决定了大多数命令的上下文。 'bt' 是这个命令的别名。

u(p) [count]

将当前帧计数(默认为一)在堆栈跟踪中向上移动(到较旧的帧)。

d(own) [count]

将堆栈跟踪中的当前帧计数(默认为一级)向下移动(到较新的帧)。

蟒蛇3

# importing pdb
import pdb
  
# simple function
def fxn(i):
    print(i)
    return
  
# set trace
pdb.set_trace()
for i in range(5):
    fxn(i)

输出: