python自帶的pdb庫,可以實(shí)現(xiàn)簡(jiǎn)單的調(diào)試功能,基本命令與gdb類似,pdb主要支持多斷點(diǎn)設(shè)置(可條件設(shè)置),代碼級(jí)單步調(diào)試,查看堆棧信息,代碼查看。
Pdb的使用主要有以下幾種
import pdb
直接在代碼里需要開始調(diào)試的地方寫入一個(gè)pdb.set_trace()語句,這樣就可以設(shè)置一個(gè)斷點(diǎn),程序會(huì)在pdb.set_trace()處暫停并進(jìn)入pdb調(diào)試環(huán)境(相當(dāng)于IDE環(huán)境下設(shè)置斷點(diǎn)),如下面一個(gè)判斷某數(shù)字是否是素?cái)?shù)的函數(shù)
#mytest.py文件
import pdb? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #導(dǎo)入pdb
import math
def func(num):
? ? if num<=1:
? ? ? ? return -1
? ? pdb.set_trace()? ? ? ? ? ? ? ? ? ? ? ? ? ? #設(shè)置斷點(diǎn)
? ? if num>2:
? ? ? ? for i in range(2,math.ceil(math.sqrt(num))):
? ? ? ? ? ? if num%i==0:
? ? ? ? ? ? ? ? print ('是合數(shù)')
? ? ? ? ? ? ? ? return
? ? print ('是質(zhì)數(shù)')
func(11)
運(yùn)行該文件,如
[root@localhost newtest]# python3 mytest.py
> /newtest/mytest.py(8)func()
-> if num>2:
(Pdb)
可以看出,遇到斷點(diǎn)后,程序進(jìn)入調(diào)試模式,且執(zhí)行流停留在接下來要執(zhí)行的語句上。>后面信息指明了當(dāng)前程序接下來將要運(yùn)行哪一行;->后面的語句即是將要運(yùn)行的語句;(Pdb)后面就可以輸入調(diào)試命令了。
現(xiàn)在就可以用pdb 命令調(diào)試了,一些常用指令:
? h(elp) [comman]? #打印可用指令及幫助信息
? n(ext)? ,執(zhí)行下一個(gè)語句,如果本句是函數(shù),則把該函數(shù)當(dāng)做一條語句,執(zhí)行該函數(shù)然后返回
(Pdb) n
> /newtest/mytest.py(9)func()
-> for i in range(2,math.ceil(math.sqrt(num))):? ? ? ? ? ? ? ? ? ? #尚未開始迭代
(Pdb) n
> /newtest/mytest.py(10)func()
-> if num%i==0:
(Pdb)
? s(tep) ,執(zhí)行下一個(gè)語句,若為函數(shù)則進(jìn)入函數(shù)體,指向函數(shù)體的第一句
? a(rgs)? ,打印當(dāng)前函數(shù)的參數(shù)
(Pdb) a
num = 11
(Pdb)
? p(rint)? ,打印某個(gè)變量
(Pdb) p i
2
(Pdb) n
> /newtest/mytest.py(9)func()
-> for i in range(2,math.ceil(math.sqrt(num))):? ? ? ? ? ? ? #11%2條件為假,又回到 for語句進(jìn)行循環(huán)
(Pdb) n
> /newtest/mytest.py(10)func()
-> if num%i==0:
(Pdb) p i
3
(Pdb)
? unt(il),執(zhí)行到下一行
作用是跳出循環(huán),或者當(dāng)前堆棧結(jié)束,比如遇到了一個(gè)for循環(huán),我們想迅速運(yùn)行完這個(gè)循環(huán),就可以使用此命令
(Pdb) p i
2
(Pdb) unt? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #結(jié)束for循環(huán)
> /newtest/mytest.py(11)func()
-> print ('是質(zhì)數(shù)')
(Pdb) p i
3
(Pdb)
可以發(fā)現(xiàn)執(zhí)行until把整個(gè)循環(huán)走了一遍,然后才到下一行。
如果輸入PDB不認(rèn)識(shí)的命令,PDB會(huì)把他當(dāng)做Python語句在當(dāng)前環(huán)境下執(zhí)行。這樣我們可以人為修改某些變量,從而改變程序的行為,如
(Pdb) a
num = 11
(Pdb) num=21? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #修改參數(shù)
(Pdb) s
> /newtest/mytest.py(4)func()
-> if num<=1:
(Pdb) s
> /newtest/mytest.py(6)func()
-> if num>2:
(Pdb) s
> /newtest/mytest.py(7)func()
-> for i in range(2,math.ceil(math.sqrt(num))):
(Pdb) s? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #進(jìn)入循環(huán)
> /newtest/mytest.py(8)func()
-> if num%i==0:
(Pdb) until? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #循環(huán)運(yùn)行結(jié)束
> /newtest/mytest.py(9)func()
-> print ('是合數(shù)')
(Pdb) s
是合數(shù)
> /newtest/mytest.py(10)func()
-> return
(Pdb)
-m pdb
上面的方式,需要改動(dòng)源代碼文件,多有不便。我們可以通過命令 python -m pdb xxx.py 啟動(dòng)腳本,進(jìn)入單步執(zhí)行模式。如
[root@localhost newtest]# python3 -m pdb mytest.py
> /newtest/mytest.py(2)<module>()
-> import math? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #將要執(zhí)行腳本第一條語句
(Pdb)
這種調(diào)試模式下,一些常用指令:
? b(reak),添加斷點(diǎn)
? ? ? ? b line_no:當(dāng)前腳本的line_no行添加斷點(diǎn)
(Pdb) b 6? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # if num>2: 處設(shè)置斷點(diǎn)
Breakpoint 1 at /newtest/mytest.py:6
(Pdb)
b 列出當(dāng)前所有斷點(diǎn),和斷點(diǎn)執(zhí)行到統(tǒng)計(jì)次數(shù)
(Pdb) b
Num Type? ? ? ? Disp Enb? Where
1? breakpoint? keep yes? at /newtest/mytest.py:6
(Pdb)
? ? ? ? 其中,num顯示了斷點(diǎn)編號(hào)。
b filename:line_no:腳本filename的line_no行添加斷點(diǎn)
? ? ? ? ? b function:在函數(shù)function的第一條可執(zhí)行語句處添加斷點(diǎn)
? cl(ear),清除斷點(diǎn)
? ? ? ? cl 清除所有斷點(diǎn)
? ? ? ? ? cl bpnumber1 bpnumber2... 清除斷點(diǎn)號(hào)為bpnumber1,bpnumber2...的斷點(diǎn)
(Pdb) cl 1? ? ? ? ? ? ? ? ? ? ? ? #刪除第一個(gè)斷點(diǎn)
Deleted breakpoint 1 at /newtest/mytest.py:6
(Pdb)
? c(ontinue)繼續(xù)執(zhí)行,直到遇到下一條斷點(diǎn)
? l(ist) ,查看指定代碼段
first_line_no, last_line_no,列出first--second范圍的代碼,如果second<first,second將被解析為行數(shù)
(Pdb) list 6,8
? 6 B? ? ? if num>2:
? 7? ? ? ? ? ? for i in range(2,math.ceil(math.sqrt(num))):
? 8? ? ? ? ? ? ? ? if num%i==0:
(Pdb)
如果沒有指定范圍,則列出當(dāng)前執(zhí)行語句周圍11條代碼。
? run:重新啟動(dòng)debug,相當(dāng)于restart
(Pdb) run
Restarting mytest.py with arguments:
? ? ? ? mytest.py
> /newtest/mytest.py(2)<module>()
-> import math
(Pdb)
? j line_no:(jump)設(shè)置語句跳轉(zhuǎn)
(Pdb) j 6? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #跳轉(zhuǎn)到第六行語句
> /newtest/mytest.py(6)<module>()
-> if num>2:
(Pdb)
? 直接輸入Enter,會(huì)重復(fù)執(zhí)行上一條命令
(Pdb) cl
Clear all breaks? y
(Pdb)? ? ? ? ? ? ? ? ? ? ? ? ? ? #回車
Clear all breaks? y
(Pdb)
? q(uit),退出debug