使用pdb模块调试Python程序实例

时间:2022-09-13 14:26:25

在Python中,语法错误可以被Python解释器发现,但逻辑上错误或变量使用错误却不容易发现,如果结果没有符合预期,则需要调试,一个很好的调试工具:Python自带的pdb模块。pdb是Python自带的调试模块。使用pdb模块可以为脚本设置断点、单步执行、查看变量值等。

pdb可以用命令行参数的方式启动,也可以使用import 将其导入后再使用。

复制代码 代码如下:

>>> dir(pdb) 
['Pdb', 'Repr', 'Restart', 'TESTCMD',.....,'re', 'run', 'runcall', 'runctx', 'runeval', 'set_trace', 'sys', 'test', 'traceback'] 


常见的pdb函数有以下几个:

 

【pdb.run()函数】

>>> 该函数主要用于调试语句块
>>> 基本用法如下

复制代码 代码如下:

>>> help(pdb.run) 
Help on function run in module pdb: 
 
run(statement, globals=None, locals=None) 
>>>参数含义

 

statement: 要调试的语句块,以字符串的形式表示
globals:   可选参数,设置statement运行的全局环境变量
locals:     可选参数,设置statement运行的局部环境变量
>>>简单示例

复制代码 代码如下:

>>> import pdb                # 导入调试模块 
>>> pdb.run('''''               # 调用run()函数执行一个for循环
for i in range(3):
    i *= 3
    print(i)
    ''') 
> <string>(2)<module>()      
(Pdb) n                       # (Pdb)为调试命令提示符,表示可输入调试命令 
> <string>(3)<module>() 
(Pdb) n                       # n(next)表示执行下一行 
> <string>(4)<module>() 
(Pdb) print(i)                # 打印变量i的值 

(Pdb) continue                # 继续运行程序 


 

【pdb.runeval()函数】
>>>该函数主要用于调试表达式
>>>基本用法如下

复制代码 代码如下:

>>> help(pdb.runeval) 
Help on function runeval in module pdb: 
 
runeval(expression, globals=None, locals=None) 

 

>>> 参数含义

expression: 要调试的,
globals:   可选参数,设置statement运行的全局环境变量
locals:     可选参数,设置statement运行的局部环境变量

>>> 简单示例

复制代码 代码如下:

>>> import pdb                  # 导入pdb模块 
>>> lst = [1, 2, 3]             # 定义一个列表 
>>> pdb.runeval('lst[1]')       # 调用runaval()函数来调试表达式lst[1] 
> <string>(1)<module>() 
(Pdb) n                         # 进入调试状态,使用n命令,单步执行 
--Return-- 
> <string>(1)<module>()->2 
(Pdb) n                         # 单步执行 
2                               # 返回表达式的值 
>>> pdb.runeval('3 + 5*6/2')    # 使用runaval()函数来调试表达式3+5*6/2 
> <string>(1)<module>()->2 
(Pdb) n 
--Return-- 
> <string>(1)<module>()->18 
(Pdb) n                         # 使用n命令单步执行 
18                              # 最后得出表达式的值 

 

【pdb.runcall()函数】

>>>该函数主要用于调试函数
>>>基本用法如下

复制代码 代码如下:

>>> help(pdb.runcall) 
Help on function runcall in module pdb: 
 
runcall(*args, **kwds) 

 

>>> 参数含义
function:          函数名
args(kwds):        函数的参数
>>> 简单示例

复制代码 代码如下:

>>> import pdb                           # 导入模块 
>>> def sum(*args):                      # 定义函数sum,求所有参数之和 
    res = 0 
    for arg in args: 
        res += arg 
    return res 
 
>>> pdb.runcall(sum, 1, 2, 3, 4)         # 使用runcall调试函数sum 
> <pyshell#53>(2)sum() 
(Pdb) n                                  # 进入调试状态,单步执行 
> <pyshell#53>(3)sum() 
(Pdb) n                                  # 单步执行 
> <pyshell#53>(4)sum()        
(Pdb) print(res)                         # 使用print打印res的值 

(Pdb) continue                           # 继续执行 
10 
>>> pdb.runcall(sum, 1, 2, 3, 4, 5, 6)   # 调用runcall调试函数sum,参数不同 
 
> <pyshell#53>(2)sum()                
(Pdb) continue                           # 继续执行 
21                                       # 函数最后返回结果 

 

【pdb.set_trace()函数】

>>>该函数主要用于脚本中设置硬断点
>>>基本用法如下

复制代码 代码如下:

>>> help(pdb.set_trace) 
Help on function set_trace in module pdb: 
 
set_trace() 

 

>>>简单示例

复制代码 代码如下:

# file: test.py 
 
import pdb 
 
pdb.set_trace() 
for i in range(5): 
    i *= 5 
    print(i) 

 

运行脚本后显示:

复制代码 代码如下:

> d:\learn\python\test.py(6)<module>() 
-> for i in range(5): 
(Pdb) list                     # 使用list列出脚本内容 
  1     # file: test.py 
  2      
  3     import pdb 
  4      
  5     pdb.set_trace()        # 使用set_trace()设置硬断点 
  6  ->  for i in range(5): 
  7         i *= 5 
  8         print(i) 
[EOF]                          # 列出脚本内容结束 
(Pdb) continue                 # 使用continue继续执行 


10 
15 
20 

 

【pdb调试命令】
pdb中的调试命令可以完成单步执行、打印变量值、设置断点等功能。pdb主要命令如下

复制代码 代码如下:

------------------------------------------------------------------------------ 
# 完整命令                    简写命令                      描述 
------------------------------------------------------------------------------ 
# args                         a                            打印当前函数的参数 
# break                        b                            设置断点 
# clear                        cl                           清除断点 
# condition                    无                           设置条件断点 
# continue                     c                            继续运行,直到遇到断点或者脚本结束 
# disable                      无                           禁用断点 
# enable                       无                           启用断点 
# help                          h                           查看pdb帮助 
# ignore                       无                           忽略断点 
# jump                         j                            跳转到指定行数运行 
# list                         l                            列出脚本清单 
# next                         n                            执行下条语句,遇到函数不进入其内部 
# print                        p                            打印变量值 
# quit                         q                            退出pdb 
# return                       r                            一致运行到函数返回 
# tbreak                       无                           设置临时断点、断点只中断一次 
# step                         s                            执行下一条语句,遇到函数进入其内部 
# where                        w                            查看所在的位置 
# !                           无                           在pdb中执行语句                     


>>>简单示例

复制代码 代码如下:

# -*- coding:gbk -*- 
# file: prime.py 

import math 
# isprime函数判断一个整数是否为素数 
# 如果i能被2到i的平方根内的任意一个数整除, 
# 则i不是素数,返回0,否则i是素数,返回1。 
def isprime(i): 
    for t in range(2, int(math.sqrt(i)) + 1): 
        if i % t == 0: 
            return 0 
 
 
print('100~110之间素数有: ') 
for i in range(100, 110): 
    if isprime(i): 
        print(i) 

 

先运行下面命令:

复制代码 代码如下:

d:\Learn\Python>python -m pdb prime.py 

 

后输入以下命令:

复制代码 代码如下:

d:\Learn\Python>python -m pdb prime.py 
> d:\learn\python\prime.py(4)<module>() 
-> import math 
(Pdb) list                                           # 运行前面命令后停在这里,list默认只列出11行 
  1     # -*- coding:gbk -*- 
  2     # file: prime.py 
  3     # 
  4  -> import math 
  5     # isprime函数判断一个整数是否为素数 
  6     # 如果i能被2到i的平方根内的任意一个数整除, 
  7     # 则i不是素数,返回0,否则i是素数,返回1。 
  8     def isprime(i): 
  9         for t in range(2, int(math.sqrt(i)) + 1): 
 10             if i % t == 0: 
 11                 return 0 
(Pdb) l 14,17                                        # 使用list命令,列出14行,到17行 
 14     print('100~110之间素数有: ') 
 15     for i in range(100, 110): 
 16         if isprime(i): 
 17             print(i) 
(Pdb) b 14                                           # 使用break命令设置断点 
Breakpoint 1 at d:\learn\python\prime.py:14          # 返回断点编号: 1 
(Pdb) b isprime                                      # 在函数isprime设置断点 
Breakpoint 2 at d:\learn\python\prime.py:8           # 返回断点编号: 2 
(Pdb) c                                              # 使用c命令运行运行脚本 
> d:\learn\python\prime.py(14)<module>()             # 停在断点1处,即第14行 
-> print('100~110之间素数有: ') 
(Pdb) c                                              # 使用c命令继续运行脚本 
100~110之间素数有:                                   # 第14行脚本输出 
> d:\learn\python\prime.py(9)isprime()               # 停在断点2,即isprime函数处 
-> for t in range(2, int(math.sqrt(i)) + 1): 
(Pdb) b 15                                           # 在第15行处设置断点 
Breakpoint 3 at d:\learn\python\prime.py:15 
(Pdb) disable 2                                      # 禁用断点2,即isprime函数处的断点 
(Pdb) c                                              # 使用c命令继续运行脚本 
> d:\learn\python\prime.py(15)<module>()             # 停在断点3处,即第15行 
-> for i in range(100, 110): 
(Pdb) print(i)                                       # 使用print打印变量i的值 
100 
(Pdb) c                                              # 继续运行脚本 
> d:\learn\python\prime.py(15)<module>() 
-> for i in range(100, 110): 
(Pdb) p i                                            # 打印i的值 
101 
(Pdb) enable 2                                       # 恢复断点2,即isprime函数处的断点 
(Pdb) c                                              # 继续运行脚本 
> d:\learn\python\prime.py(9)isprime()                
-> for t in range(2, int(math.sqrt(i)) + 1): 
(Pdb) n                                              # 单步执行下一条语句                                           
> d:\learn\python\prime.py(10)isprime() 
-> if i % t == 0: 
(Pdb) print(t)                                       # 使用print打印变量t的值 

(Pdb) cl                                             # 清楚所有断点,输入y确认 
Clear all breaks? y 
(Pdb) c                                              # 继续运行脚本 
103 
105 
107 
109 
(Pdb) q                                              # 使用quit(q)退出pdb调试