使用Python中PDB模块中的命令来调试Python代码的教程

你有多少次陷入不得不更改别人代码的境地?如果你是一个开发团队的一员,那么你遇到上述境地的次数比你想要的还要多。然而,Python中有一个整洁的调试特性(像其他大多数语言一样),在这种情况下使用非常方便。本文是一篇快速教程,希望它能让你的编码生活更加容易。
1. 一个混乱的程序

出于本教程的目的,让我们研究一下下面的简单程序。

这个程序接收两个命令行参数,然后执行加法和减法操作。

(假设用户输入的是有效值,因此代码中我们没有进行错误处理。)

import sys
def add(num1=0, num2=0):
  return int(num1) + int(num2)
def sub(num1=0, num2=0):
  return int(num1) - int(num2)
def main():
  #Assuming our inputs are valid numbers
  print sys.argv
  addition = add(sys.argv[1], sys.argv[2])
  print addition
  subtraction = sub(sys.argv[1], sys.argv[2])
  print subtraction
if __name__ == '__main__':
  main()

2. PDB

Python提供了一个有用的模块PDB,它实际上是一个交互式源代码调试器。

你需要下面的两行代码来使用此模块。

import pdb
pdb.set_trace()

看一下我们修改过的程序,里面包含了一些断点。

import pdb
import sys
def add(num1=0, num2=0):
  return int(num1) + int(num2)
def sub(num1=0, num2=0):
  return int(num1) - int(num2)
def main():
  #Assuming our inputs are valid numbers
  print sys.argv
  pdb.set_trace() # <-- Break point added here
  addition = add(sys.argv[1], sys.argv[2])
  print addition
  subtraction = sub(sys.argv[1], sys.argv[2])
  print subtraction
if __name__ == '__main__':
  main()

3. 程序执行触发调试器

一旦你设置好断点以后,你就可以像平时一样执行程序。

python debugger.py 1 2

程序将会在遇到的第一个断点处停止执行。

['debugger.py']
> /Users/someuser/debugger.py(15)main()
-> addition = add(sys.argv[1], sys.argv[2])
(Pdb)

我们在第14行设置了一个断点,所以我们能看到将要执行的下一行是第15行。可以看到,在执行到第15行之前程序已经停止。

在这里我们有几个选项,让我们在下面步骤中看看一些调试指令。
4. 下一行->n

在你的调试器提示中,输入n运行到下一行。

> /Users/someuser/debugger.py(14)main()
-> addition = add(sys.argv[1], sys.argv[2])
(Pdb) n
> /Users/someuser/debugger.py(15)main()
-> print addition

这会执行当前行代码,并准备执行下一行。

我们可以使用n来逐行执行整个程序,但这其实没有什么用处。

可能你已经看到,PDB实际上并没有进入我们的add函数中。下面,就让我们看看其他几个令调试更加有趣的选项。

注意:
    一个更酷的特性是你可以单击回车键来执行以前的命令(在本例中只要指令n)。

5. 打印->p

下面,我们再次开始调试程序。(你可以通过单击c使PDB跳到末尾或者直到下一个断点,因为程序中我们并没有其他的断点了,所有程序将会执行完成。)

['debugger.py', '1', '2']
> /Users/someuser/debugger.py(14)main()
-> addition = add(sys.argv[1], sys.argv[2])
(Pdb)

现在,如果我们想知道sys.argv中包含什么内容,我们可以输入以下内容:

-> addition = add(sys.argv[1], sys.argv[2])
(Pdb) p sys.argv
['debugger.py', '1', '2']
(Pdb) p sys.argv[1]
'1'
(Pdb)

使用这种方法可以相当方便地查看变量中实际存储着什么值。

现在我们将进入加法函数内部。
6. 单步->s

我们可以使用“s”进入加法函数内部。

(Pdb) s
--Call--
> /Users/someuser/debugger.py(4)add()
-> def add(num1=0, num2=0):
(Pdb) n
> /Users/someuser/debugger.py(5)add()
-> return int(num1) + int(num2)
(Pdb)

这将把我们带入加法函数的内部,现在我们可以在加法函数内部使用n、p和其他的操作指令。

此时单击“r”将会把我们带到前面进入函数的返回语句。

如果你想快速跳转到一个函数的结尾处,那么这个指令将很有用。
7. 动态添加断点- > b

前面,在程序运行之前,我们使用pdb.set_trace()设置了一个断点。

不过,经常在调试会话已经开始之后,我们想要在程序中特定的地方添加断点。

这里我们就可以使用选项“b”来实现这种目的。

我们重新开始执行程序。

['debugger.py', '1', '2']
> /Users/someuser/debugger.py(15)main()
-> addition = add(sys.argv[1], sys.argv[2])
(Pdb)

此时我在第18行设置一个断点。

-> addition = add(sys.argv[1], sys.argv[2])
(Pdb) b 18
Breakpoint 1 at /Users/someuser/debugger.py:18
(Pdb) c
We are in add--
3
> /Users/someuser/debugger.py(18)main()
-> print subtraction
(Pdb) p subtraction
-1
(Pdb)

从上面我们可以看到,PDB跳到了第18行并等待下一个指令。

同时,PDB还为该断点分配了一个号码(在本例中是1)。为了以后的执行,我们可以通过开启或禁用断点号码来启用或停用对应的断点。
8. 列表->l

有时在调试的时候,你可能会忘记此时你处在代码的什么地方。在这种情况下,使用“l”将会打印出一个友好的总结,它能够显示出此刻你在代码中的位置。

['debugger.py', '1', '2']
> /Users/someuser/debugger.py(15)main()
-> addition = add(sys.argv[1], sys.argv[2])
(Pdb) l
 10
 11   def main():
 12     #Assuming our inputs are valid numbers
 13     print sys.argv
 14     pdb.set_trace() # <-- Break point added here
 15 ->   addition = add(sys.argv[1], sys.argv[2])
 16     print addition
 17     subtraction = sub(sys.argv[1], sys.argv[2])
 18     print subtraction

9. 动态分配变量

在调试会话期间,你可以分配变量来帮助你进行调试,知道这些对你来说也是有帮助的。例如:

['debugger.py', '1', '2']
> /Users/someuser/debugger.py(15)main()
-> addition = add(sys.argv[1], sys.argv[2])
(Pdb) n
We are in add--
> /Users/someuser/debugger.py(16)main()
-> print addition
(Pdb) p addition
3 #<--- addition here is 3
(Pdb) addition = 'this is now string' #<--- We changed the value of additon
(Pdb) n
this is now string #<--- Now when we print it we actually gets it as a string. that we just set above.
> /Users/someuser/debugger.py(17)main()
-> subtraction = sub(sys.argv[1], sys.argv[2])

注意:
如果你想设置一些如n(即PDB指令)这样的变量,你应该使用这种指令:

(Pdb) !n=5
(Pdb) p n
5

10. 结束->q

最后,在代码的任何地方如果你想结束调试,可以使用“q”,那么正在执行的程序将会终止。
11. 扩展阅读

本文只涉及到了PDB的表面用法,其实使用PDB你还可以做到更多(PDB 文档)。

使用IPython的人可以在ipdb中找到一个更好的调试器,它提供了tab补充、语法高亮和其他一些很酷的特性。

(0)

相关推荐

  • 总结用Pdb库调试Python的方式及常用的命令

    用Pdb调试有多种方式 使用 Pdb调试 Python的程序的方式主要是下面的三种!下面逐一介绍 命令行加-m参数 命令行启动目标程序,加上-m参数,这样调用 testPdb.py的话断点就是程序执行的第一行之前 本文接下来重点讲到的实例展示就是使用这种方式进行调试的! python -m pdb testPdb.py 在python交互环境调试 >>> import pdb >>> import testPdb >>> pdb.run('testPd

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

    在Python中,语法错误可以被Python解释器发现,但逻辑上错误或变量使用错误却不容易发现,如果结果没有符合预期,则需要调试,一个很好的调试工具:Python自带的pdb模块.pdb是Python自带的调试模块.使用pdb模块可以为脚本设置断点.单步执行.查看变量值等. pdb可以用命令行参数的方式启动,也可以使用import 将其导入后再使用. 复制代码 代码如下: >>> dir(pdb)  ['Pdb', 'Repr', 'Restart', 'TESTCMD',.....,'

  • 使用PDB简单调试Python程序简明指南

    在 Python 中也可以像 gcc/gdb 那样调试程序,只要在运行 Python 程序时引入 pdb 模块(假设要调试的程序名为 d.py): 复制代码 代码如下: $ vi d.py #!/usr/bin/python def main():         i, sum = 1, 0         for i in xrange(100):                 sum = sum + i         print sum if __name__ == '__main__'

  • python pdb调试方法分享

    复制代码 代码如下: import pdb def pdb_test(arg):    for i in range(arg):        print(i)    return arg pdb.run("pdb_test(3)") b 函数名.行号: 打断点,b可以查询所有的断点. 复制代码 代码如下: (Pdb) b pdb_testBreakpoint 1 at c:\users\plpcc\desktop\pdbtest.py:3(Pdb) bNum Type        

  • 使用PDB模式调试Python程序介绍

    以前在windows下一直用的idel带的功能调试python程序,在linux下没调试过.(很多时候只是print)就从网上查找一下~ 方法: 复制代码 代码如下: python -m pdb a.py a.py是python文件. (Pdb)模式下的常用命令: q 退出debug h 即help,打印所有可以命令 h w 打印命令 w 的含意 n 执行当前行直到到达下一行或直到它返回 s 执行当前行,一有可能就停止(比如当前行有一个函数调用).它和n(next)的区别是当前行中有函数调用时s

  • python的pdb调试命令的命令整理及实例

    python的pdb调试命令的命令整理及实例 一.命令整理 pdb调试命令 完整命令 简写命令 描述 args a 打印当前函数的参数 break b 设置断点 clear cl 清除断点 condition 无 设置条件断点 continue c或者cont 继续运行,知道遇到断点或者脚本结束 disable 无 禁用断点 enable 无 启用断点 help h 查看pdb帮助 ignore 无 忽略断点 jump j 跳转到指定行数运行 list l 列出脚本清单 next n 执行下条语

  • Python中使用PDB库调试程序

    Python自带的pdb库,发现用pdb来调试程序还是很方便的,当然了,什么远程调试,多线程之类,pdb是搞不定的. 用pdb调试有多种方式可选: 1. 命令行启动目标程序,加上-m参数,这样调用myscript.py的话断点就是程序的执行第一行之前 复制代码 代码如下: python -m pdb myscript.py 2. 在Python交互环境中启用调试 复制代码 代码如下: >>> import pdb >>> import mymodule >>

  • 使用Python中PDB模块中的命令来调试Python代码的教程

    你有多少次陷入不得不更改别人代码的境地?如果你是一个开发团队的一员,那么你遇到上述境地的次数比你想要的还要多.然而,Python中有一个整洁的调试特性(像其他大多数语言一样),在这种情况下使用非常方便.本文是一篇快速教程,希望它能让你的编码生活更加容易. 1. 一个混乱的程序 出于本教程的目的,让我们研究一下下面的简单程序. 这个程序接收两个命令行参数,然后执行加法和减法操作. (假设用户输入的是有效值,因此代码中我们没有进行错误处理.) import sys def add(num1=0, n

  • python中pdb模块实例用法

    大家可能都不大熟悉关于pdb这个模块,实际上就是python中的内置模块,主要作用于命令行调试代码,下面我们将通过是哪个小结给大家详细介绍下使用该内容的方式,首先是简单介绍,然后为大家呈现实例,最后就是总结啦,小伙伴是不是相当期待呢,那就板正做好,一起来详细了解下吧~ 简单介绍: 添加断点-代码后添加一行 pdb.set_trace() 命令行添加断点 b line_number 常见命令: 进入命令行Debug模式,python -m pdb xxx.py h:(help)帮助 w:(wher

  • 对Python中TKinter模块中的Label组件实例详解

    Python2.7.4 OS-W7x86 1. 简介 Label用于在指定的窗口中显示文本和图像.最终呈现出的Label是由背景和前景叠加构成的内容. Label组件定义函数:Label(master=None, cnf={}, **kw) 其中,kw参数是用来自定义lable组件的键值对. 2. 背景自定义 背景的话,有三部分构成:内容区+填充区+边框 <1>内容区参数有:width,length用于指定区域大小,如果显示前景内容是文本,则以单个字符大小为单位:如果显示的是图像,则以像素为单

  • Python编程functools模块中创建修改函数的高阶函数解析

    partial 函数 partial 为偏函数(有的地方也叫做部分应用函数),它是对函数的二次封装,将现有函数的部分参数提前绑定为指定值,然后再进行计算. 由于偏函数的可变参数少,因此函数调用的难度低. 直接展示代码: from functools import partial # 原函数声明 def show(name, level): print("name:", name, "level:", level) # 定义偏函数,封装 show() 函数,并为 na

  • Python 利用argparse模块实现脚本命令行参数解析

    study.py内容如下 #!/usr/bin/env python # -*- coding:utf-8 -*- __author__ = 'shouke' import argparse def argparseFunc(): ''' 基于argparse模块实现命令参数解析功能 执行示例: python study.py -i 172.19.7.236 -p 8080 -a -r python study.py --ip 172.19.7.236 --port 7077 --auth -w

  • python的random模块及加权随机算法的python实现方法

    random是用于生成随机数的,我们可以利用它随机生成数字或者选择字符串. •random.seed(x)改变随机数生成器的种子seed. 一般不必特别去设定seed,Python会自动选择seed. •random.random()    用于生成一个随机浮点数n,0 <= n < 1 •random.uniform(a,b)    用于生成一个指定范围内的随机浮点数,生成的随机整数a<=n<=b; •random.randint(a,b)    用于生成一个指定范围内的整数,a

  • Python使用random模块实现掷骰子游戏的示例代码

    引入内容 根据人民邮电出版社出版的<Python程序设计现代设计方法>P102习题中的第7题--掷骰子游戏,进行代码编写. 题目要求 一盘游戏中,两人轮流掷骰子5次,并将每次掷出的点数累加,5局之后,累计点数较大者获胜,点数相同则为平局.根据此规则实现掷骰子游戏,并算出50盘之后的胜利者( 50盘中嬴得盘数最多的,即最终胜利者). 审题: 共有50盘游戏.一盘游戏有5局,每一局双方各掷骰子一次,5局结束以后统计分数,分数高的一方获胜.至此,一盘游戏结束.50盘游戏结束后,赢得盘数最多的一方为最

  • Python的math模块中的常用数学函数整理

    在数学之中,除了加减乘除四则运算之外--这是小学数学--还有其它更多的运算,比如乘方.开方.对数运算等等,要实现这些运算,需要用到 Python 中的一个模块:Math 模块(module)是 Python 中非常重要的东西,你可以把它理解为 Python 的扩展工具.换言之,Python 默认情况下提供了一些可用的东西,但是这些默认情况下提供的还远远不能满足编程实践的需要,于是就有人专门制作了另外一些工具.这些工具被称之为"模块" 任何一个 Pythoner 都可以编写模块,并且把这

  • Python的time模块中的常用方法整理

    在应用程序的开发过程中,难免要跟日期.时间处理打交道.如:记录一个复杂算法的执行时间:网络通信中数据包的延迟等等.Python中提供了time, datetime calendar等模块来处理时间日期,今天对time模块中最常用的几个函数作一个介绍. time.time time.time()函数返回从1970年1月1日以来的秒数,这是一个浮点数. time.sleep 可以通过调用time.sleep来挂起当前的进程.time.sleep接收一个浮点型参数,表示进程挂起的时间. time.cl

  • 在Python的struct模块中进行数据格式转换的方法

    Python是一门非常简洁的语言,对于数据类型的表示,不像其他语言预定义了许多类型(如:在C#中,光整型就定义了8种),它只定义了六种基本类型:字符串,整数,浮点数,元组,列表,字典.通过这六种数据类型,我们可以完成大部分工作.但当Python需要通过网络与其他的平台进行交互的时候,必须考虑到将这些数据类型与其他平台或语言之间的类型进行互相转换问题.打个比方:C++写的客户端发送一个int型(4字节)变量的数据到Python写的服务器,Python接收到表示这个整数的4个字节数据,怎么解析成Py

随机推荐