真叫人头秃!Python也有pdb
文 |?軒轅御龍
來(lái)源:Python 技術(shù)「ID: pythonall」
C有g(shù)db,Python也有pdb
寫(xiě)過(guò)C語(yǔ)言的同學(xué)們想必都很懷念(讀者:?)gdb調(diào)試器,使用gdb可以隨意在程序運(yùn)行過(guò)程中暫停流程、查看變量。
很多時(shí)候,我們單純分析代碼流程和日志信息無(wú)法定位的問(wèn)題,都得靠調(diào)試器來(lái)幫忙;可以說(shuō)有了調(diào)試器,程序員才是代碼世界完整的上帝。
Python當(dāng)然也不示弱,同樣存在這樣的巴別塔可以讓人升天
01——不過(guò)阿醬必須承認(rèn)的是,現(xiàn)代IDE集成的圖形化調(diào)試功能已經(jīng)很好使了,一般情況下使用命令行工具的場(chǎng)景并不多。
但是也確實(shí)存在無(wú)法使用圖形化IDE的情況,因此對(duì)pdb工具略作了解還是很有必要的。畢竟誰(shuí)也不知道可能被扔給一個(gè)什么樣的環(huán)境啊哈哈
pdb的使用
作為解釋型語(yǔ)言,Python調(diào)試工具的使用跟gdb畢竟還是有區(qū)別的。
比如Python的調(diào)試就不需要什么符號(hào)表之類(lèi)的東西,說(shuō)到底,最終Python虛擬機(jī)執(zhí)行的邏輯也是自帶符號(hào)的。
也正是由于Python的這種特殊性,所有pdb其實(shí)有兩種不太一樣的使用方式,即侵入式和非侵入式。
其實(shí)按字面意思就很容易理解在兩種方式的使用。類(lèi)比一下腦機(jī)接口,也分為侵入式和非侵入式。侵入式就表示要將電極、芯片植入大腦皮層,“侵入”人體;而非侵入式則是在頭骨外收集腦電波進(jìn)行分析。
同樣地,侵入式pdb調(diào)用就是將調(diào)用pdb的代碼直接寫(xiě)入Python腳本當(dāng)中;而非侵入式則是從命令行調(diào)用pdb,執(zhí)行相應(yīng)被調(diào)試腳本。
侵入式pdb
使用方式如下代碼所示,在代碼中途插入一行調(diào)用:
import?pdb;?#?pdb.set_trace()a?=?"just" b?=?"do"pdb.set_trace()c?=?['p',?'y',?'t',?'h',?'o',?'n'] print(a)運(yùn)行腳本,會(huì)進(jìn)入這樣一個(gè)交互式界面:
D:\000-GitHub\python-examples\xuanyuanyulong\2020-11-04-python-pdb>python?test_pdb_intrusive.py >?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py(21)<module>() ->?c?=?['p',?'y',?'t',?'h',?'o',?'n'] (Pdb)到這里已經(jīng)啟動(dòng)了pdb,并且打印內(nèi)容中-> c = ['p', 'y', 't', 'h', 'o', 'n']行首的箭頭,表示當(dāng)前程序執(zhí)行流到了這一行代碼,如果繼續(xù)執(zhí)行,將首先執(zhí)行該行。
非侵入式pdb
非侵入式要xue微簡(jiǎn)單一些,最大的好處是不需要改動(dòng)代碼。
我們?cè)诳刂婆_(tái)執(zhí)行以下命令:
D:\000-GitHub\python-examples\xuanyuanyulong\2020-11-04-python-pdb>python?-m?pdb?test_pdb_intrusive.py >?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py(1)<module>() ->?import?pdb;?#?pdb.set_trace() (Pdb)可以看到,通過(guò)這種方式進(jìn)入調(diào)試,程序執(zhí)行流停在了程序開(kāi)頭。
通過(guò)分析進(jìn)入調(diào)試時(shí)代碼執(zhí)行流的位置,我們可以發(fā)現(xiàn),實(shí)際上侵入式的插入pdb.set_trace()調(diào)用,等價(jià)于我們從命令行啟動(dòng)pdb,然后在這個(gè)調(diào)用的下一行打了一個(gè)斷點(diǎn),然后直接運(yùn)行程序。
簡(jiǎn)單命令
gdb中有一些常用的簡(jiǎn)單命令,本節(jié)阿醬帶大家熟悉一下,后續(xù)會(huì)做更深入的討論。
h(elp)
在pdb界面下輸入h或help命令,即可列出pdb中支持的各種命令:
(Pdb)?hDocumented?commands?(type?help?<topic>): ======================================== EOF????c??????????d????????h?????????list??????q????????rv???????undisplay a??????cl?????????debug????help??????ll????????quit?????s????????unt alias??clear??????disable??ignore????longlist??r????????source???until args???commands???display??interact??n?????????restart??step?????up b??????condition??down?????j?????????next??????return???tbreak???w break??cont???????enable???jump??????p?????????retval???u????????whatis bt?????continue???exit?????l?????????pp????????run??????unalias??whereMiscellaneous?help?topics: ========================== exec??pdb在pdb后帶一個(gè)命令作為參數(shù),還可進(jìn)一步看到相應(yīng)的使用說(shuō)明:
(Pdb)?h?h h(elp)Without?argument,?print?the?list?of?available?commands.With?a?command?name?as?argument,?print?help?about?that?command."help?pdb"?shows?the?full?pdb?documentation."help?exec"?gives?help?on?the?!?command.相信我,help其實(shí)才是pdb里面最重要的命令。別的什么都可以記不住,但是help一定要記住。在以結(jié)果為導(dǎo)向的職場(chǎng)生活中也是一樣,遇到問(wèn)題要及時(shí)求助喲~
l(ist)
打印當(dāng)前文件的源代碼。不帶參數(shù)的話,默認(rèn)打印當(dāng)前行前后共計(jì)11行代碼。繼續(xù)執(zhí)行該命令的話,則會(huì)繼續(xù)往后打印最多11行代碼,直到遇上文件結(jié)束符EOF。
用.作為參數(shù)則限定要強(qiáng)一點(diǎn),只會(huì)打印當(dāng)前行前后11行代碼。
(Pdb)?l1??->?import?pdb;?#?pdb.set_trace()234?????def?addStr(a,?b):5?????????return?a?+?b68?????????return?''.join(l)910?????def?getSlogan(a,?b,?c):11?????????result?=?addStr(a,?b)?+?mergeChar(c)當(dāng)指定兩個(gè)參數(shù)時(shí),則打印這個(gè)區(qū)間內(nèi)的代碼:
(Pdb)?l?3,?734?????def?addStr(a,?b):5?????????return?a?+?b67??->?def?mergeChar(l:?list):而當(dāng)?shù)诙€(gè)參數(shù)b比第一個(gè)參數(shù)a小的時(shí)候,則表示“從第a行開(kāi)始,繼續(xù)往后打印b行”,也就是總共打印(1+b)行:
(Pdb)?l?7,?37??->?def?mergeChar(l:?list):8?????????return?''.join(l)910?????def?getSlogan(a,?b,?c):p/pp
打印某個(gè)對(duì)象的值。區(qū)別在于pp調(diào)用的是pprint函數(shù),打印更加美觀。
(Pdb)?p?a 'just' (Pdb)?p?addStr <function?addStr?at?0x000002087B0F9C80>!
使用!可以在pdb環(huán)境下,執(zhí)行一般的Python語(yǔ)句。通常我們可以用來(lái)改變變量的值——要不怎么說(shuō)調(diào)試器可以讓你成為上帝呢?還有比這更為所欲為的嗎?
一般的話這個(gè)!其實(shí)可以省略,但是當(dāng)要執(zhí)行語(yǔ)句開(kāi)頭的單詞與pdb的已有命令沖突,就得不到預(yù)期結(jié)果了,所以建議還是加上。
這個(gè)用!領(lǐng)起命令的做法跟vim編輯器的邏輯很像,可以類(lèi)比記憶。不熟悉的讀者可以忽略。
(Pdb)?!a?=?"python" (Pdb)?p?a 'python'r(eturn)
pdb中,r和return表示同一個(gè)意思,即“運(yùn)行當(dāng)前函數(shù)直到返回”。
這一點(diǎn)上,r在pdb和gdb中的含義是不同的。讀者不必在意
run/restart
表示重新運(yùn)行當(dāng)前被調(diào)試程序。使用這個(gè)命令,可以為需要傳入?yún)?shù)的腳本傳入所需參數(shù)。
格式與命令行執(zhí)行該腳本一樣,只是把相應(yīng)的python命令和腳本路徑替換為了run或restart。
(Pdb)?run?a?b?c?d?kkk Restarting?test_pdb_intrusive.py?with?arguments:test_pdb_intrusive.py >?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py(1)<module>() ->?import?pdb;?#?pdb.set_trace() (Pdb)?!import?sys (Pdb)?p?sys.argv ['test_pdb_intrusive.py',?'a',?'b',?'c',?'d',?'kkk']b(reak)
查看/添加斷點(diǎn)。
不帶任何參數(shù)時(shí),即列出當(dāng)前已有斷點(diǎn)。
(Pdb)?b?21 Breakpoint?1?at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:21 (Pdb)?b?17 Breakpoint?2?at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:17 (Pdb)?b Num?Type?????????Disp?Enb???Where 1???breakpoint???keep?yes???at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:21 2???breakpoint???keep?yes???at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:17同時(shí),通過(guò)run和restart重新運(yùn)行被調(diào)試程序,不會(huì)清除已有斷點(diǎn):
(Pdb)?run Restarting?test_pdb_intrusive.py?with?arguments:test_pdb_intrusive.py >?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py(1)<module>() ->?import?pdb;?#?pdb.set_trace() (Pdb)?b Num?Type?????????Disp?Enb???Where 1???breakpoint???keep?yes???at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:21 2???breakpoint???keep?yes???at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:17cl(ear)
有三種使用方式:1)類(lèi)似設(shè)置斷點(diǎn)時(shí),清除特定文件特定行的斷點(diǎn);2)將要清除的斷點(diǎn)號(hào)列出來(lái),以空格分隔;3)不帶參數(shù),清除所有斷點(diǎn)。
下面一一演示:
1)類(lèi)似設(shè)置斷點(diǎn)時(shí),清除特定文件特定行的斷點(diǎn)
(Pdb)?b Num?Type?????????Disp?Enb???Where 1???breakpoint???keep?yes???at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:21 2???breakpoint???keep?yes???at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:17 (Pdb)?clear?test_pdb_intrusive.py:21 (Pdb)?b Num?Type?????????Disp?Enb???Where 2???breakpoint???keep?yes???at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:172)將要清除的斷點(diǎn)號(hào)列出來(lái),以空格分隔
(Pdb)?b?21 Breakpoint?3?at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:21 (Pdb)?b?15 Breakpoint?4?at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:15 (Pdb)?b Num?Type?????????Disp?Enb???Where 2???breakpoint???keep?yes???at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:17 3???breakpoint???keep?yes???at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:21 4???breakpoint???keep?yes???at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:15 (Pdb)?clear?2?4 Deleted?breakpoint?2?at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:17 Deleted?breakpoint?4?at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:15 (Pdb)?b Num?Type?????????Disp?Enb???Where 3???breakpoint???keep?yes???at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:213)不帶參數(shù),清除所有斷點(diǎn)
(Pdb)?b?17 Breakpoint?5?at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:17 (Pdb)?b?15 Breakpoint?6?at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:15 (Pdb)?b Num?Type?????????Disp?Enb???Where 3???breakpoint???keep?yes???at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:21 5???breakpoint???keep?yes???at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:17 6???breakpoint???keep?yes???at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:15 (Pdb)?b Num?Type?????????Disp?Enb???Where 3???breakpoint???keep?yes???at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:21 5???breakpoint???keep?yes???at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:17 6???breakpoint???keep?yes???at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:15 (Pdb)?clear Clear?all?breaks??yes Deleted?breakpoint?3?at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:21 Deleted?breakpoint?5?at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:17 Deleted?breakpoint?6?at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:15 (Pdb)?b好了打住打住,寫(xiě)之前感覺(jué)pdb沒(méi)多少東西,沒(méi)想到寫(xiě)起來(lái)才發(fā)現(xiàn),這么一點(diǎn)內(nèi)容就已經(jīng)這么多了,今天又熬夜了……
02狗命要緊各位讀者老爺后會(huì)有期、后會(huì)有期
總結(jié)
pdb的內(nèi)容出乎意料地豐富,還有很多內(nèi)容在這篇文章中都沒(méi)能涉及。
軟件調(diào)試其實(shí)也是一門(mén)很有趣的學(xué)問(wèn),當(dāng)然,也是一門(mén)很有用的學(xué)問(wèn)
由于微信平臺(tái)算法改版,公號(hào)內(nèi)容將不再以時(shí)間排序展示,如果大家想第一時(shí)間看到我們的推送,強(qiáng)烈建議星標(biāo)我們和給我們多點(diǎn)點(diǎn)【在看】。星標(biāo)具體步驟為:
總結(jié)
以上是生活随笔為你收集整理的真叫人头秃!Python也有pdb的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 专家解读:阅读AI论文对找工作有帮助吗?
- 下一篇: 资源分享 | 统计学最全思维导图,附下载