Hom's Blog


Python:Debug-pdb模块

pdb是python debugger 调试器. 他既可以在命令行执行python时进行调试,也可以作为模块被调用.

执行调试模式

运行python使用: python -m pdb mysqcript.py 则会进入调试模式,

# > /Users/Hom/MyGit/DailyTools/scripts/ExtractXYZR.py(9)<module>()
# -> import os,sys
(Pdb) # 会自动停在第一行,等待调试,这时你可以看看 帮助
(Pdb) h # 使用帮助

# Documented commands (type help <topic>):
# ========================================
# EOF    bt         cont      enable  jump  pp       run      unt
# a      c          continue  exit    l     q        s        until
# alias  cl         d         h       list  quit     step     up
# args   clear      debug     help    n     r        tbreak   w
# b      commands   disable   ignore  next  restart  u        whatis
# break  condition  down      j       p     return   unalias  where
# 
# Miscellaneous help topics:
# ==========================
# exec  pdb
# 
# Undocumented commands:
# ======================
# retval  rv

(Pdb) h b  # 查询具体指令帮助
# b(reak) ([file:]lineno | function) [, condition]
# With a line number argument, set a break there in the current
# file.  With a function name, set a break at first executable line
# of that function.  Without argument, list all breaks.  If a second
# argument is present, it is a string specifying an expression
# which must evaluate to true before the breakpoint is honored.
# 
# The line number may be prefixed with a filename and a colon,
# to specify a breakpoint in another file (probably one that
# hasn't been loaded yet).  The file is searched for on sys.path;
# the .py suffix may be omitted.
(Pdb) q # 退出调试模式

说明下几个关键命令, 括号内是长命令. 要是不输入东西直接确认将重复上一个命令. ;;可以将多行命令写在一行.

功能

  • h (help) # 帮助, 列出可用命令, h command 可用查看具体命令
  • q (quit) # 退出
  • !statement # 在目前的环境中执行statement (就是执行指定python语句)。
  • alias name command # 以一个”别名”代替”一群出错命令”,有点类似c/c++ 的 macro。可在.pdbrc文件内定义..
  • unalias name # 取消某个 alias定义的别名。
  • run # 重新运行脚本. 后面可以跟参数, 会覆盖原来sys.argv保存的参数. 2.6后新加.

断点设置

  • b lineno (break) # 断点设置在本py的第 lineno 行, 或 b ots.py:20 #断点设置到 ots.py第20行. b funcname #断点设置到指定函数处; b # 查看所有断点编号及信息
  • tbreak lineno # 临时断点, 用法同break, 但只能断一次.
  • cl num (clear) # 删除第 num 个断点, num由b列出的Num列决定.如果没有带参数,则清除所有断点。也可指定行号.
  • condition bpnumber [condition] # 设置断点条件, 不写条件则会取消条件设置.
  • disable bpnumber # 取消指定断点的功能,但仍然保留断点可以重新激活。不指定 bpnumber会失效暂停所有断点.
  • enable bpnumber # 恢复断点的功能。
  • ignore bpnumber count # 设定断点的忽略次数。如果没指定count,其初始为0。当count为0时,断点会正常动作。若有指定 count,则每次执行到该中断,count就少1,直到count数为0。
  • commands bpnumber # 设置断点号处执行指定命令.使用该命令后进入cmd模式,然后可以输入相关要执行的命令, 输入end结束. 直接输入end会取消相应号的命令. 2.5版新加

运行

  • c (continue) # 继续运行直到下个断点
  • n (next) # 单步运行, 不会进入函数内部而是直接到下一行.
  • s (step) # 单步运行, 但会进入到调用函数的内部.
  • r (return) # 继续执行直到函数返回处(return的地方).
  • j lineNo (jump) # 跳到某行执行,可以前跳或后跳。不是所有行都可跳. 只有在 call stack 的最底部才能作用。
  • unt (until) # 继续执行直到行号大于当前行. ?? 2.6后新加.

查看

  • l (list) # 列出目前所在档案中的位置。->所指是现在所在代码(一般是可执行代码,默认上下5行). 连续地 l 命令会一直列到档案结尾。指定一个数字参数 n, 就是列出该行上下文; 两个参数n,m, 就是一个范围(n<m) 或指定行及以后的m行.
  • p var (print) # 查看变量 var 当前值
  • pp 和 p 命令类似,但是使用 pprint module。
  • a (args) # 查看全部栈内当前函数的参数变量
  • w (where) 列出目前call stack 中的所在层。(调用栈中的处理)
  • d (down) 在call stack中往下移一层 (较新).
  • u (up) 在call stack中往上移一层(较旧)。如果在上移一层之后按下 n ,则会在上移之后的一层执行下一个叙述,之前的 function call 就自动返回。
完整命令 简写命令 描述
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 查看所在的位置
alias 别名
unalias 取消别名
在pdb中执行语句

一个debug示例:

python -m pdb prime.py  
> ./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 ./prime.py:14          # 返回断点编号: 1  
(Pdb) b isprime                                      # 在函数isprime设置断点  
Breakpoint 2 at ./prime.py:8           # 返回断点编号: 2  
(Pdb) c                                              # 使用c命令运行运行脚本  
> ./prime.py(14)<module>()             # 停在断点1处,即第14行  
-> print('100~110之间素数有: ')  
(Pdb) c                                              # 使用c命令继续运行脚本  
100~110之间素数有:                                   # 第14行脚本输出  
> ./prime.py(9)isprime()               # 停在断点2,即isprime函数处  
-> for t in range(2, int(math.sqrt(i)) + 1):  
(Pdb) b 15                                           # 在第15行处设置断点  
Breakpoint 3 at ./prime.py:15  
(Pdb) disable 2                                      # 禁用断点2,即isprime函数处的断点  
(Pdb) c                                              # 使用c命令继续运行脚本  
> ./prime.py(15)<module>()             # 停在断点3处,即第15行  
-> for i in range(100, 110):  
(Pdb) print(i)                                       # 使用print打印变量i的值  
100  
(Pdb) c                                              # 继续运行脚本  
> ./prime.py(15)<module>()  
-> for i in range(100, 110):  
(Pdb) p i                                            # 打印i的值  
101  
(Pdb) enable 2                                       # 恢复断点2,即isprime函数处的断点  
(Pdb) c                                              # 继续运行脚本  
> ./prime.py(9)isprime()                 
-> for t in range(2, int(math.sqrt(i)) + 1):  
(Pdb) n                                              # 单步执行下一条语句                                            
> ./prime.py(10)isprime()  
-> if i % t == 0:  
(Pdb) print(t)                                       # 使用print打印变量t的值  
2  
(Pdb) cl                                             # 清楚所有断点,输入y确认  
Clear all breaks? y  
(Pdb) c                                              # 继续运行脚本  
103  
105  
107  
109  
(Pdb) q                                              # 使用quit(q)退出pdb调试 

使用pdb模块

在python中使用pdb模块可以进行调试.

import pdb

  • pdb.set_trace() : 设置断点, 在运行脚本到此时进入pdb模式, 指令则指到下一行.
  • pdb.run(statement, globals=None, locals=None): 主要用于调试指定内容语句块.
    • statement: 要调试的语句块,以字符串的形式表示
    • globals: 可选参数,设置statement运行的全局环境变量
    • locals: 可选参数,设置statement运行的局部环境变量
  • pdb.runeval(statement, globals=None, locals=None): 和run类似, 但会对statement字符串先进行运算
  • pdb.runcall(funcname, *args, **kwds): 调试指定函数.后面可以指定传递的函数参数. 多参数要用,隔开.
  • pdb.post_mortem([traceback]): post-mortem调试模式处理traceback或新近的错.
  • pdb.pm(): post-mortem调试模式处理sys.last_traceback 的反馈

另外还有pdb类, 此处不作介绍.

Reference

  1. pdb — The Python Debugger


◆ 本文地址: http://platinhom.github.io/2015/11/04/pyDebug/, 转载请注明 ◆

前一篇: Github提交个人修改到开源项目
后一篇: Python:序列化模块pickle和cpickle


Contact: Hom / 已阅读()
Source 类别: Coding  标签: Python