PDB python调试

本文详细介绍了Python调试工具pdb的使用方法,包括通过set_trace()设置断点、使用.pdbrc文件预设调试命令、命令行启动调试、breakpoint()函数、pdb.pm()和pdb.post_mortem()的区别及应用场景。还讲解了常用pdb命令,如设置断点、继续执行、打印变量、忽略断点、条件断点和动态改变变量值等。
部署运行你感兴趣的模型镜像

 方法一:

先import pdb,

语句pdb.set_trace()设置断点

然后写好代码后直接运行

到set_trace()的地方会停下来,

方法二:

使用.pdbrc隐藏文件,提前写好进入pdb后要执行的cmd。和待调试的python脚本放在同一个目录下

#断点
b 57
b lib/evalor.py:48
b lib/metric.py:109
c

#跳过训练
j 59
c

#读入事先准备好的特征文件,跳过提取特征
import numpy as np
features = np.load('feat.npy')
j 52
c

#停在metric.py的109行,打印一下重要变量
print(features.shape)
print(topk)
print(self.setting)
————————————————

 方法三:

使用命令行

python -m pdb test.py #直接调试这个test.py脚本

方法四:

在python 3.7以后只是breakpoint(),直接使用breakpoint()写到需要的断点处,就不需要Import pdb

def combine(s1,s2):      # define subroutine combine, which... 
    s3 = s1 + s2 + s1    # sandwiches s2 between copies of s1, ... 
    s3 = '"' + s3 +'"'   # encloses it in double quotes,... 
    return s3            # and returns it. 
a = "aaa"
b = "bbb"
c = "ccc"
breakpoint()
-》final = combine(a,b) 
print(final)

 方法五:

事发调试,当错误发生以后,在Import pdb, 有两种方法

pdb.pm()

例子,写一个错误脚本

a=1
b=c

 运行

= RESTART: C:/Users/Administrator/AppData/Local/Programs/Python/Python38/pdb_test4.py
Traceback (most recent call last):
  File "C:/Users/Administrator/AppData/Local/Programs/Python/Python38/pdb_test4.py", line 2, in <module>
    b=c
NameError: name 'c' is not defined

出现错误以后,马上用pdb.pm()能否直接定位到上一次出错的地方,而不需要再跑一边脚本
>>> import pdb
>>> pdb.pm()
> c:\users\administrator\appdata\local\programs\python\python38\pdb_test4.py(2)<module>()
-> b=c
(Pdb) list
  1  	a=1
  2  ->	b=c
[EOF]
(Pdb) 

pdb.post_mortem(traceback)

与PM不同,需要给出具体的traceback对象,不给的话, 就是默认当前handle的那个

示例,使用sys.last_traceback获得最近一次的trackback对象。传递给post_mortem。可以获得和pdb.pm()一样的效果

= RESTART: C:/Users/Administrator/AppData/Local/Programs/Python/Python38/pdb_test4.py
Traceback (most recent call last):
  File "C:/Users/Administrator/AppData/Local/Programs/Python/Python38/pdb_test4.py", line 2, in <module>
    b=c
NameError: name 'c' is not defined
>>> import sys
>>> sys.last_traceback
<traceback object at 0x0000001F15F1F200>
>>> obj=sys.last_traceback
>>> import gdb
Traceback (most recent call last):
  File "<pyshell#20>", line 1, in <module>
    import gdb
ModuleNotFoundError: No module named 'gdb'
>>> import pdb
>>> pdb.post_mortem(trackback=obj)
Traceback (most recent call last):
  File "<pyshell#22>", line 1, in <module>
    pdb.post_mortem(trackback=obj)
TypeError: post_mortem() got an unexpected keyword argument 'trackback'
>>> pdb.post_mortem(obj)

三个函数的区别 

共同点都是开始执行函数的时候出现pdb提示符,进去调试,执行完函数里的东西以后,就自动退出了调试

run(statementglobals=Nonelocals=None)

用来调试语句,没有返回值,例子

import pdb
s='''a=1
c=3
b=a+c
a=0
c=b/a
print(c)'''

pdb.run(s)
> <string>(1)<module>()
(Pdb) list
[EOF]
(Pdb) l first
*** Error in argument: 'first'
(Pdb) n
> <string>(2)<module>()
(Pdb) n
> <string>(3)<module>()
(Pdb) n
> <string>(4)<module>()
(Pdb) n
> <string>(5)<module>()
(Pdb) n
ZeroDivisionError: division by zero
> <string>(5)<module>()
(Pdb) n
--Return--
> <string>(5)<module>()->None
(Pdb) n
Traceback (most recent call last):
  File "C:/Users/Administrator/AppData/Local/Programs/Python/Python38/pdb_test4.py", line 9, in <module>
    pdb.run(s)
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python38\lib\pdb.py", line 1596, in run
    Pdb().run(statement, globals, locals)
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python38\lib\bdb.py", line 587, in run
    exec(cmd, globals, locals)
  File "<string>", line 5, in <module>
ZeroDivisionError: division by zero
>>> 

runeval(expressionglobals=Nonelocals=None)

用来调试表达式,如果表达式有返回值,那么runeval就有返回值

import pdb
def combine(s1,s2):      # define subroutine combine, which... 
    s3 = s1 + s2 + s1    # sandwiches s2 between copies of s1, ... 
    s3 = '"' + s3 +'"'   # encloses it in double quotes,... 
    return s3            # and returns it. 
a = "aaa"
#pdb.set_trace()
b = "bbb"
c = "ccc"
final=pdb.runeval('combine("aaa","bbb")')
c=final
b="haha"
print(b)
#final = combine(a,b)
d="hehe"
print(d)
print("c is {}".format(c))

runcall(function*args**kwds)

用来调试一个函数,有返回值,返回值就是这个函数的返回值

例子

写一个函数,用pdb.runcall(function,参数1,参数2)来传递,有

import pdb
def combine(s1,s2):      # define subroutine combine, which... 
    s3 = s1 + s2 + s1    # sandwiches s2 between copies of s1, ... 
    s3 = '"' + s3 +'"'   # encloses it in double quotes,... 
    return s3            # and returns it. 
a = "aaa"
#pdb.set_trace()
b = "bbb"
c = "ccc"
final=pdb.runcall(combine,"aaa","bbb")
#注意不能写成combine("aaa","bbb"),这里的参数传递要用位置信息来收集成元组
c=final
b="haha"
print(b)
d="hehe"
print(d)
print("c is {}".format(c))

下面是一些常用命令

命令解释
break 或 b 设置断点

设置断点

b     #展示所有断点

b 3  #在第三行设置断点

b 函数名 #在行数第一行设置断点

tbreak临时断点,执行一次就删除,用法和break一样
cl

清除断点

cl   #清除所有断点

cl  断点号   #清除指定的断点,断点号用b查

cl python文件名:行数  #清除这个文件的这一行的断点

disable [bpnumber]停用断点
enable [bpnumber]启用断点
ignore [bpnumber] [count]忽略某个断点多少次
condition [bpnumber] [condition]

stop only if condition is true

condition 1 #clear all the conditions

condition 1 a==3 #当a==3的时候,停下来,注意不是a=3

condition只能添加一个

continue 或 c继续执行程序,直到下一个断点
until lineno继续执行程序,直到指定的行
list 或 l

查看当前行的代码段,

list        #当前执行语句附近11行

list 3     #第三行代码的附件的11行

list 3,5   #列出3到5行

jump linenojump 4   #指针指向第四行
source objectsource 函数名 #会打印出函数的代码
whatis object会显示出这个object的类型,比如function , int等
commands?
run/restart ?
display监视一个表达式,或者一个变量,当他们的值发生变量的时候,就会自动打印出来
undisplay取消监视一个表达式,或者一个变量
interact
alias为很长的python语句取一个别名
unalias
!statement在当前指向的语句前执行的语句,如果语句的第一个字符或者单词和pdb的命令相似,那么!号不可以省略,可以用分号来隔开两个语句
retval没成功,? Print the return value for the last return of a function.
debug code直接debug 一行code,不影响原来的代码
step 或 s进入函数
a(args)列入当前函数的所有参数,通常先用s进入,然后用a,展出所有形参的值
return 或 r执行代码直到从当前函数返回
exit 或 q中止并退出
next 或 n执行下一行
pp或者p

打印变量的值
p  a #打印出a的值

p  expression #打印出表达式的值,比如a+b

help帮助
enter重复执行上一条命令

 用b设置断点:

(Pdb) b 15
Breakpoint 2 at c:\users\administrator\appdata\local\programs\python\python38\pdb_test2.py:15
(Pdb) b 14
*** Blank or comment
(Pdb) b
Num Type         Disp Enb   Where
1   breakpoint   keep yes   at c:\users\administrator\appdata\local\programs\python\python38\pdb_test2.py:11
	breakpoint already hit 1 time
2   breakpoint   keep yes   at c:\users\administrator\appdata\local\programs\python\python38\pdb_test2.py:15
(Pdb) list
  7  	pdb.set_trace()
  8  	b = "bbb"
  9  	c = "ccc"
 10  	final=combine("aaa","bbb")
 11 B	c=final
 12  ->	b="haha"
 13  	print(b)
 14  	#final = combine(a,b)
 15 B	d="hehe"
 16  	print(d)
 17  	print("c is {}".format(c))
(Pdb)
(Pdb) b combine
Breakpoint 3 at c:\users\administrator\appdata\local\programs\python\python38\pdb_test2.py:2
(Pdb) list 1
  1  	import pdb
  2 B	def combine(s1,s2):      # define subroutine combine, which...
  3  	    s3 = s1 + s2 + s1    # sandwiches s2 between copies of s1, ...
  4  	    s3 = '"' + s3 +'"'   # encloses it in double quotes,...
  5  	    return s3            # and returns it.
  6  	a = "aaa"
  7  	pdb.set_trace()
  8  	b = "bbb"
  9  	c = "ccc"
 10  	final=combine("aaa","bbb")
 11 B	c=final
(Pdb)  

continue和exit的区别

continue:会一次性执行到下一个set_trace()的点,如果没有下一个set_trace的话,就会直接执行到程序结束退出

exit:直接退出pd调试,不继续执行

打印变量的值:

比如a是变量名,那么就是pp a 或者p a

具体list的用法:

使用list以后,会打印出代码段,并且箭头指向还没有执行的下一行

> c:\users\administrator\appdata\local\programs\python\python38\pdb_test1.py(4)<module>()
-> b = "bbb"
(Pdb) l
  1  	import pdb
  2  	a = "aaa"
  3  	pdb.set_trace()
  4  ->	b = "bbb"
  5  	c = "ccc"
  6  	pdb.set_trace()
  7  	final = a + b + c
  8  	print(final)
[EOF]
(Pdb) c
> c:\users\administrator\appdata\local\programs\python\python38\pdb_test1.py(7)<module>()
-> final = a + b + c
(Pdb) l
  2  	a = "aaa"
  3  	pdb.set_trace()
  4  	b = "bbb"
  5  	c = "ccc"
  6  	pdb.set_trace()
  7  ->	final = a + b + c
  8  	print(final)
[EOF]
(Pdb) c
aaabbbccc
>>> 

进入函数调试

s:当箭头指向一行代码,该代码是在调用一个函数,此时输入s,会进入函数,进去以后,里面的调试方法一样

r:顺序执行当前的代码直到下一个return,停下来,此时return还没有执行

使用ignore调试循环中的断点

1.先用b 行号来设置断点

2.使用b来查看断点号,描述里也可以看到这个断点被执行了几次

3.使用ignore 断点号 次数    ,来设置ignore的次数。

4.使用b再次查看,可以看到ignore next 10hits的字样。

5.这个时候直接输入c命令,就可以定位到底10次循环的地方

(Pdb) list
  1  	import pdb
  2  	def loop(num):
  3  	    for i in range(num):
  4 B->	        print("this is {}".format(i))
  5  	num=20
  6  	pdb.set_trace()
  7  	a=1
  8  	b=2
  9  	c=3
 10  	loop(num)
 11  	
(Pdb) b
Num Type         Disp Enb   Where
1   breakpoint   keep yes   at c:\users\administrator\appdata\local\programs\python\python38\pdb_test5.py:4
	breakpoint already hit 3 times
(Pdb) ignore 1 10
Will ignore next 10 crossings of breakpoint 1.
(Pdb) list
 12  	
 13  	
[EOF]
(Pdb) list 1
  1  	import pdb
  2  	def loop(num):
  3  	    for i in range(num):
  4 B->	        print("this is {}".format(i))
  5  	num=20
  6  	pdb.set_trace()
  7  	a=1
  8  	b=2
  9  	c=3
 10  	loop(num)
 11  	
(Pdb) b
Num Type         Disp Enb   Where
1   breakpoint   keep yes   at c:\users\administrator\appdata\local\programs\python\python38\pdb_test5.py:4
	ignore next 10 hits
	breakpoint already hit 3 times
(Pdb) c
this is 3
this is 4
this is 5
this is 6
this is 7
this is 8
this is 9
this is 10
this is 11
this is 12
this is 13
> c:\users\administrator\appdata\local\programs\python\python38\pdb_test5.py(4)loop()
-> print("this is {}".format(i))
(Pdb) b
Num Type         Disp Enb   Where
1   breakpoint   keep yes   at c:\users\administrator\appdata\local\programs\python\python38\pdb_test5.py:4
	breakpoint already hit 14 times
(Pdb) 

使用condition在循环 中使用断点

condition 1 i==3

stop only if i==3 

-> a=1
(Pdb) list 1
  1  	import pdb
  2  	def loop(num):
  3  	    for i in range(num):
  4  	        print(i)
  5  	        print("this is {}".format(i))
  6  	num=20
  7  	pdb.set_trace()
  8  ->	a=1
  9  	b=2
 10  	c=3
 11  	loop(num)
(Pdb) b 5
Breakpoint 1 at c:\python38\pdb_test5.py:5
(Pdb) b
Num Type         Disp Enb   Where
1   breakpoint   keep yes   at c:\python38\pdb_test5.py:5
(Pdb) condition b i==3
*** Non-numeric breakpoint number b
(Pdb) condition 1 i==3
New condition set for breakpoint 1.
(Pdb) b
Num Type         Disp Enb   Where
1   breakpoint   keep yes   at c:\python38\pdb_test5.py:5
	stop only if i==3
(Pdb) c
0
this is 0
1
this is 1
2
this is 2
3
> c:\python38\pdb_test5.py(5)loop()
-> print("this is {}".format(i))
(Pdb) n
this is 3
> c:\python38\pdb_test5.py(3)loop()
-> for i in range(num):
(Pdb) c
4
this is 4
5
this is 5
6
this is 6
7
this is 7
8
this is 8
9
this is 9
10
this is 10
11
this is 11
12
this is 12
13
this is 13
14
this is 14
15
this is 15
16
this is 16
17
this is 17
18
this is 18
19
this is 19
>>> 

在调试的时候动态改变值

a=1

b=2+a

正常情况下顺序执行,b会被赋值为3,但是如果在执行b=2+a之前,输入!a=4,那么再按n+enter, b的值会变成6

(Pdb) p a
1
(Pdb) p b
*** NameError: name 'b' is not defined
(Pdb) ! a=4
*** IndentationError: unexpected indent
(Pdb) !a=4
(Pdb) p a
4
(Pdb) list 1
  1  	import pdb
  2  	def loop(num):
  3  	    for i in range(num):
  4  	        print(i)
  5  	        print("this is {}".format(i))
  6  	num=20
  7  	pdb.set_trace()
  8  	a=1
  9  ->	b=2+a
 10  	c=3
 11  	loop(num)
(Pdb) n
> c:\python38\pdb_test5.py(10)<module>()
-> c=3
(Pdb) p b
6
(Pdb) 

监视循环中i的值

> c:\python38\pdb_test5.py(8)<module>()
-> a=1
(Pdb) list
  3  	    for i in range(num):
  4  	        print(i)
  5  	        print("this is {}".format(i))
  6  	num=20
  7  	pdb.set_trace()
  8  ->	a=1
  9  	b=2+a
 10  	c=3
 11  	loop(num)
[EOF]
(Pdb) b 3
Breakpoint 1 at c:\python38\pdb_test5.py:3
(Pdb) b
Num Type         Disp Enb   Where
1   breakpoint   keep yes   at c:\python38\pdb_test5.py:3
(Pdb) list 1
  1  	import pdb
  2  	def loop(num):
  3 B	    for i in range(num):
  4  	        print(i)
  5  	        print("this is {}".format(i))
  6  	num=20
  7  	pdb.set_trace()
  8  ->	a=1
  9  	b=2+a
 10  	c=3
 11  	loop(num)
(Pdb) c
> c:\python38\pdb_test5.py(3)loop()
-> for i in range(num):
(Pdb) display i
display i: ** raised NameError: name 'i' is not defined **
(Pdb) n
> c:\python38\pdb_test5.py(4)loop()
-> print(i)
display i: 0  [old: ** raised NameError: name 'i' is not defined **]
(Pdb) n
0
> c:\python38\pdb_test5.py(5)loop()
-> print("this is {}".format(i))
(Pdb) n
this is 0
> c:\python38\pdb_test5.py(3)loop()
-> for i in range(num):
(Pdb) n
> c:\python38\pdb_test5.py(4)loop()
-> print(i)
display i: 1  [old: 0]
(Pdb) 

您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值