欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2023-03-27 20:36:05
在Python中,语法错误可以被Python解释器发现,但逻辑上错误或变量使用错误却不容易发现,如果结果没有符合预期,则需要调试,一个很好的调试工具:Python自带的pd...

在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调试