真叫人头秃!Python也有pdb
文 |?軒轅御龍
來源:Python 技術「ID: pythonall」
C有gdb,Python也有pdb
寫過C語言的同學們想必都很懷念(讀者:?)gdb調試器,使用gdb可以隨意在程序運行過程中暫停流程、查看變量。
很多時候,我們單純分析代碼流程和日志信息無法定位的問題,都得靠調試器來幫忙;可以說有了調試器,程序員才是代碼世界完整的上帝。
Python當然也不示弱,同樣存在這樣的巴別塔可以讓人升天
01——不過阿醬必須承認的是,現代IDE集成的圖形化調試功能已經很好使了,一般情況下使用命令行工具的場景并不多。
但是也確實存在無法使用圖形化IDE的情況,因此對pdb工具略作了解還是很有必要的。畢竟誰也不知道可能被扔給一個什么樣的環境啊哈哈
pdb的使用
作為解釋型語言,Python調試工具的使用跟gdb畢竟還是有區別的。
比如Python的調試就不需要什么符號表之類的東西,說到底,最終Python虛擬機執行的邏輯也是自帶符號的。
也正是由于Python的這種特殊性,所有pdb其實有兩種不太一樣的使用方式,即侵入式和非侵入式。
其實按字面意思就很容易理解在兩種方式的使用。類比一下腦機接口,也分為侵入式和非侵入式。侵入式就表示要將電極、芯片植入大腦皮層,“侵入”人體;而非侵入式則是在頭骨外收集腦電波進行分析。
同樣地,侵入式pdb調用就是將調用pdb的代碼直接寫入Python腳本當中;而非侵入式則是從命令行調用pdb,執行相應被調試腳本。
侵入式pdb
使用方式如下代碼所示,在代碼中途插入一行調用:
import?pdb;?#?pdb.set_trace()a?=?"just" b?=?"do"pdb.set_trace()c?=?['p',?'y',?'t',?'h',?'o',?'n'] print(a)運行腳本,會進入這樣一個交互式界面:
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)到這里已經啟動了pdb,并且打印內容中-> c = ['p', 'y', 't', 'h', 'o', 'n']行首的箭頭,表示當前程序執行流到了這一行代碼,如果繼續執行,將首先執行該行。
非侵入式pdb
非侵入式要xue微簡單一些,最大的好處是不需要改動代碼。
我們在控制臺執行以下命令:
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)可以看到,通過這種方式進入調試,程序執行流停在了程序開頭。
通過分析進入調試時代碼執行流的位置,我們可以發現,實際上侵入式的插入pdb.set_trace()調用,等價于我們從命令行啟動pdb,然后在這個調用的下一行打了一個斷點,然后直接運行程序。
簡單命令
gdb中有一些常用的簡單命令,本節阿醬帶大家熟悉一下,后續會做更深入的討論。
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后帶一個命令作為參數,還可進一步看到相應的使用說明:
(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其實才是pdb里面最重要的命令。別的什么都可以記不住,但是help一定要記住。在以結果為導向的職場生活中也是一樣,遇到問題要及時求助喲~
l(ist)
打印當前文件的源代碼。不帶參數的話,默認打印當前行前后共計11行代碼。繼續執行該命令的話,則會繼續往后打印最多11行代碼,直到遇上文件結束符EOF。
用.作為參數則限定要強一點,只會打印當前行前后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)當指定兩個參數時,則打印這個區間內的代碼:
(Pdb)?l?3,?734?????def?addStr(a,?b):5?????????return?a?+?b67??->?def?mergeChar(l:?list):而當第二個參數b比第一個參數a小的時候,則表示“從第a行開始,繼續往后打印b行”,也就是總共打印(1+b)行:
(Pdb)?l?7,?37??->?def?mergeChar(l:?list):8?????????return?''.join(l)910?????def?getSlogan(a,?b,?c):p/pp
打印某個對象的值。區別在于pp調用的是pprint函數,打印更加美觀。
(Pdb)?p?a 'just' (Pdb)?p?addStr <function?addStr?at?0x000002087B0F9C80>!
使用!可以在pdb環境下,執行一般的Python語句。通常我們可以用來改變變量的值——要不怎么說調試器可以讓你成為上帝呢?還有比這更為所欲為的嗎?
一般的話這個!其實可以省略,但是當要執行語句開頭的單詞與pdb的已有命令沖突,就得不到預期結果了,所以建議還是加上。
這個用!領起命令的做法跟vim編輯器的邏輯很像,可以類比記憶。不熟悉的讀者可以忽略。
(Pdb)?!a?=?"python" (Pdb)?p?a 'python'r(eturn)
pdb中,r和return表示同一個意思,即“運行當前函數直到返回”。
這一點上,r在pdb和gdb中的含義是不同的。讀者不必在意
run/restart
表示重新運行當前被調試程序。使用這個命令,可以為需要傳入參數的腳本傳入所需參數。
格式與命令行執行該腳本一樣,只是把相應的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)
查看/添加斷點。
不帶任何參數時,即列出當前已有斷點。
(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同時,通過run和restart重新運行被調試程序,不會清除已有斷點:
(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)類似設置斷點時,清除特定文件特定行的斷點;2)將要清除的斷點號列出來,以空格分隔;3)不帶參數,清除所有斷點。
下面一一演示:
1)類似設置斷點時,清除特定文件特定行的斷點
(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)將要清除的斷點號列出來,以空格分隔
(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)不帶參數,清除所有斷點
(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好了打住打住,寫之前感覺pdb沒多少東西,沒想到寫起來才發現,這么一點內容就已經這么多了,今天又熬夜了……
02狗命要緊各位讀者老爺后會有期、后會有期
總結
pdb的內容出乎意料地豐富,還有很多內容在這篇文章中都沒能涉及。
軟件調試其實也是一門很有趣的學問,當然,也是一門很有用的學問
由于微信平臺算法改版,公號內容將不再以時間排序展示,如果大家想第一時間看到我們的推送,強烈建議星標我們和給我們多點點【在看】。星標具體步驟為:
總結
以上是生活随笔為你收集整理的真叫人头秃!Python也有pdb的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 专家解读:阅读AI论文对找工作有帮助吗?
- 下一篇: 资源分享 | 统计学最全思维导图,附下载