2020-08-08 python linux 調(diào)試(使用PDB )

python也有類似C語言gdb的工具pdb被啼,記錄下pdb的使用方法和心得。

基礎使用

先找了段簡單的測試程序:

#!/usr/bin/python
from ftplib import FTP
import sys
import socket
import pdb
def passwordCorrect(ip,port,username,password):
        try:
                client = FTP()
                pdb.set_trace()
                client.connect(ip,port)
                client.login(username,password)
                client.close()
        except Exception, e:
                pdb.set_trace()
                client.close()
                if str(e).find('unknown IP address')!=-1:
                        return 2
                return 0
        print "correct"
        return 1

if __name__ == '__main__':
        socket.setdefaulttimeout(3)
        ret = passwordCorrect('127.0.0.1',21,'test','test')
        print "return is ",ret

pdb的常用命令說明:

l #查看運行到哪行代碼
n #單步運行端姚,跳過函數(shù)
s #單步運行,可進入函數(shù)
p 變量 #查看變量值
b 行號 #斷點設置到第幾行
b #顯示所有斷點列表
cl 斷點號 #刪除某個斷點
cl #刪除所有斷點
c #跳到下一個斷點
r #return當前函數(shù)
exit #退出

調(diào)試記錄:

pdb設置斷點可以在程序里加入:

import pdb

在需要設置斷點的地方加入pdb.set_trace()

執(zhí)行 python pdb_test.py

1 [root@wh practice]# vim test.py
2 [root@wh practice]# python -m pdb test.py
3 > /home/practice/test.py(2)<module>()
4 -> from ftplib import FTP
5 (Pdb) c
6 > /home/practice/test.py(10)passwordCorrect()
7 -> client.connect(ip,port)

按c逐個執(zhí)行到下一個斷點挤悉,按p ip 就可以查看變量ip的值

exit退出當前函數(shù)

補充

使用 PDB 調(diào)試

python -m pdb 1.py

-m 的話渐裸,就會默認斷在第一行代碼

  • h(elp),會打印當前版本Pdb可用的命令装悲,如果要查詢某個命令刚夺,可以輸入 h [command]锣险,例如:“h l” — 查看list命令

  • l(ist),可以列出當前將要運行的代碼塊

(Pdb) l
497 pdb.set_trace()
498 base_data = {}
499 new_data = {}
500 try:
501 execfile(base_file_name,{},base_data)
502 -> execfile(new_file_name,{},new_data)
503 except:
504 logger.writeLog(“error! load result log error!”)
505 print “l(fā)oad cmp logs error!”
506 raise Exception, “l(fā)oad cmp logs error!”
507

斷點設置
(Pdb)b 10 #斷點設置在本py的第10行
或(Pdb)b ots.py:20 #斷點設置到 ots.py第20行
刪除斷點(Pdb)b #查看斷點編號
(Pdb)cl 2 #刪除第2個斷點

運行
(Pdb)n #單步運行
(Pdb)s #細點運行 也就是會下到,方法
(Pdb)c #跳到下個斷點
查看
(Pdb)p param #查看當前 變量值
(Pdb)l #查看運行到某處代碼
(Pdb)a #查看全部棧內(nèi)變量

  • b(reak)醉蚁, 設置斷點蕾殴,例如 “b 77″员舵,就是在當前腳本的77行打上斷點棒仍,還能輸入函數(shù)名作為參數(shù),斷點就打到具體的函數(shù)入口抡蛙,如果只敲b护昧,會顯示現(xiàn)有的全部斷點

(Pdb) b 504
Breakpoint 4 at /home/jchen/regression/regressionLogCMP.py:504

  • condition bpnumber [condition],設置條件斷點粗截,下面語句就是對第4個斷點加上條件“a==3”

(Pdb) condition 4 a==3
(Pdb) b
Num Type Disp Enb Where
4 breakpoint keep yes at /home/jchen/regression/regressionLogCMP.py:504
stop only if a==3

  • cl(ear)惋耙,如果后面帶有參數(shù),就是清除指定的斷點(我在Python2.4上從來沒成功過!U篱弧R=稹);如果不帶參數(shù)就是清除所有的斷點

(Pdb) cl
Clear all breaks? y

  • disable/enable蒜田,禁用/激活斷點

(Pdb) disable 3
(Pdb) b
Num Type Disp Enb Where
3 breakpoint keep no at /home/jchen/regression/regressionLogCMP.py:505

  • n(ext),讓程序運行下一行选泻,如果當前語句有一個函數(shù)調(diào)用冲粤,用n是不會進入被調(diào)用的函數(shù)體中的

  • s(tep),跟n相似页眯,但是如果當前有一個函數(shù)調(diào)用梯捕,那么s會進入被調(diào)用的函數(shù)體中

  • c(ont(inue)),讓程序正常運行窝撵,直到遇到斷點

  • j(ump)傀顾,讓程序跳轉到指定的行數(shù)

(Pdb) j 497

/home/jchen/regression/regressionLogCMP.py(497)compareLog()
-> pdb.set_trace()

  • a(rgs),打印當前函數(shù)的參數(shù)

(Pdb) a
_logger =
_base = ./base/MRM-8137.log
_new = ./new/MRM-8137.log
_caseid = 5550001
_toStepNum = 10
_cmpMap = {‘_bcmpbinarylog’: ‘True’, ‘_bcmpLog’: ‘True’, ‘_bcmpresp’: ‘True’}

  • p碌奉,最有用的命令之一短曾,打印某個變量

(Pdb) p _new
u’./new/MRM-8137.log’

  • !赐劣,感嘆號后面跟著語句嫉拐,可以直接改變某個變量

  • q(uit),退出調(diào)試

使用gdb調(diào)試Python進程

有時我們會想調(diào)試一個正在運行的Python進程魁兼,或者一個Python進程的coredump婉徘。例如現(xiàn)在遇到一個mod_wsgi的進程僵死了,不接受請求咐汞,想看看究竟是運行到哪行Python代碼呢盖呼?這時就需要祭出gdb了。

主要是三步:

1)確保你的gdb版本>=7

2)安裝python-debuginfo包(如:python-debuginfo-2.6.6-29.el6_2.2.x86_64.rpm化撕,這個版本號一定要跟你所用的python版本一致(可以rpm -qa|grep python查看你安裝的python的詳細版本號)几晤。找包http://debuginfo.centos.org/6/x86_64/

3)就可以用#gdb python 進程號,進行調(diào)試了侯谁。需要在系統(tǒng)安裝 gdb 和 Python debug 擴展锌仅。Python debug 擴展包含了一些 debug 命令,并且添加了一些 Python 特定的命令到gdb墙贱。在主流的 Linux 發(fā)行版中热芹,你可以輕松的安裝他們:

Fedora:

sudo yum install gdb python-debuginfo

Ubunt:

sudo apt-get install gdb python2.7-dbg

在一些老系統(tǒng)上面,也一樣可以使用 gdb惨撇,具體看文章末尾伊脓。

準備

1. 確認你的gdb版本是>=7,gdb從版本7開始支持對Python的debug

2.確認gdb連接的Python是所要debug的Python报腔,否則請重新編譯gdb株搔。

方法:

$ gdb
(gdb) python
> import sys
>print sys.version
>end
2.4.3 ( #1, Sep 21 2011, 19:55:41) 
[GCC 4.1.2 20080704 (Red Hat 4.1.2-51)]

在一些追求穩(wěn)定的發(fā)行版(例如CentOS),Python的版本會較低纯蛾,這時都會自己編譯一個Python使用纤房。而從源里安裝的gdb會連接源里Python的版本。例如在CentOS 5.4翻诉,源里的Python是2.4.3炮姨,從源安裝的gdb也會連接到Python 2.4.3。

使用 GDB

有兩種可行的方法:

  1. 一開始就使用 gdb 來啟動應用
  2. 連接到一個已經(jīng)運行的 Python 進程

gdb 下面啟動 Python 同樣有兩種方式:

交互式:

...
(gdb) run <programname>.py <arguments>

自動:

$ gdb -ex r --args python <programname>.py <arguments>

這樣的話碰煌,它會一直運行直到退出舒岸、段錯誤、或者人為的停止(使用 Ctrl+C)芦圾。

如果進程已經(jīng)開始運行蛾派,你可以通過 PID 來接入它:

$ gdb python <pid of running process>

調(diào)試進程

如果你的程序段錯誤了, gdb 會自動暫停程序个少,這樣你可以切換到 gdb命令行來檢查狀態(tài)洪乍。你也可以人為地使用Ctrl+C 來暫停程序運行。

查看 EasierPythonDebugging獲得 gdb 里面的 Python 命令列表夜焦。

查看 C 調(diào)用棧

如果你在 debug 段錯誤典尾,你最想做的可能就是查看 C 調(diào)用棧。

gdb 的命令行里面糊探,只要運行一下命令:

(gdb) bt
#0  0x0000002a95b3b705 in raise () from /lib/libc.so.6
#1  0x0000002a95b3ce8e in abort () from /lib/libc.so.6
#2  0x00000000004c164f in posix_abort (self=0x0, noargs=0x0)
    at ../Modules/posixmodule.c:7158
#3  0x0000000000489fac in call_function (pp_stack=0x7fbffff110, oparg=0)
    at ../Python/ceval.c:3531
#4  0x0000000000485fc2 in PyEval_EvalFrame (f=0x66ccd8)
    at ../Python/ceval.c:2163
...

運氣好的話钾埂,你可以直接看到問題出現(xiàn)在什么地方。如果它提供的信息不能直接幫你解決問題科平,你可以嘗試繼續(xù)追蹤調(diào)用棧褥紫。調(diào)式的結果取決于 debug 信息的有效程度。

查看 Python 調(diào)用棧

如果你安裝了 Python 擴展瞪慧,你可以使用

(gdb) py-bt

可以獲取熟悉的 Python 源代碼髓考。

對掛住的進程開刀

如果一個進程看上去掛住了,他可能在等待什么東西(比如鎖弃酌、IO 等等)氨菇。也有可能在拼命的跑循環(huán)。連接上這個進程妓湘,然后檢查調(diào)用棧也許可以幫上忙查蓉。

如果進程在瘋狂循環(huán),你可以先讓它運行一會榜贴,使用 cont 命令豌研,然后使用 Ctrl+C 來暫停,并且打印出調(diào)用棧。

如果一些線程卡住了鹃共,下面的命令可能會幫上忙:

(gdb) info threads
  Id   Target Id         Frame
  37   Thread 0xa29feb40 (LWP 17914) "NotificationThr" 0xb7fdd424 in __kernel_vsyscall ()
  36   Thread 0xa03fcb40 (LWP 17913) "python2.7" 0xb7fdd424 in __kernel_vsyscall ()
  35   Thread 0xa0bfdb40 (LWP 17911) "QProcessManager" 0xb7fdd424 in __kernel_vsyscall ()
  34   Thread 0xa13feb40 (LWP 17910) "python2.7" 0xb7fdd424 in __kernel_vsyscall ()
  33   Thread 0xa1bffb40 (LWP 17909) "python2.7" 0xb7fdd424 in __kernel_vsyscall ()
  31   Thread 0xa31ffb40 (LWP 17907) "QFileInfoGather" 0xb7fdd424 in __kernel_vsyscall ()
  30   Thread 0xa3fdfb40 (LWP 17906) "QInotifyFileSys" 0xb7fdd424 in __kernel_vsyscall ()
  29   Thread 0xa481cb40 (LWP 17905) "QFileInfoGather" 0xb7fdd424 in __kernel_vsyscall ()
  7    Thread 0xa508db40 (LWP 17883) "QThread" 0xb7fdd424 in __kernel_vsyscall ()
  6    Thread 0xa5cebb40 (LWP 17882) "python2.7" 0xb7fdd424 in __kernel_vsyscall ()
  5    Thread 0xa660cb40 (LWP 17881) "python2.7" 0xb7fdd424 in __kernel_vsyscall ()
  3    Thread 0xabdffb40 (LWP 17876) "gdbus" 0xb7fdd424 in __kernel_vsyscall ()
  2    Thread 0xac7b7b40 (LWP 17875) "dconf worker" 0xb7fdd424 in __kernel_vsyscall ()
* 1    Thread 0xb7d876c0 (LWP 17863) "python2.7" 0xb7fdd424 in __kernel_vsyscall ()

當前運行的線程被標記為 *鬼佣,要查看 Python 代碼運行到哪里,使用 py-list 查看:

(gdb) py-list
2025        # Open external files with our Mac app
2026        if sys.platform == "darwin" and 'Spyder.app' in __file__:
2027            main.connect(app, SIGNAL('open_external_file(QString)'),
2028                         lambda fname: main.open_external_file(fname))
2029
>2030        app.exec_()
2031        return main
2032
2033
2034    def __remove_temp_session():
2035        if osp.isfile(TEMP_SESSION_PATH):

查看所有進程的 Python 代碼位置霜浴,可以使用:

(gdb) thread apply all py-list
...
 200
 201        def accept(self):
>202            sock, addr = self._sock.accept()
 203            return _socketobject(_sock=sock), addr
 204        accept.__doc__ = _realsocket.accept.__doc__
 205
 206        def dup(self):
 207            """dup() -> socket object

Thread 35 (Thread 0xa0bfdb40 (LWP 17911)):
Unable to locate python frame

Thread 34 (Thread 0xa13feb40 (LWP 17910)):
 197            for method in _delegate_methods:
 198                setattr(self, method, dummy)
 199        close.__doc__ = _realsocket.close.__doc__
 200
 201        def accept(self):
>202            sock, addr = self._sock.accept()
 203            return _socketobject(_sock=sock), addr
...

引用

老系統(tǒng)上的 GDB

有時候你需要在老系統(tǒng)上面安裝 gdb晶衷,這時候你可能需要下列信息:

GDB Macros

一些隨著 Python 發(fā)布的 GDB 腳本可以用來調(diào)試 Python 進程。你可以把 Python 源碼里面的 Misc/gdbinit 拷貝到~/.gdbinit阴孟,或者從Subversion來拷貝他們房铭。請注意你的 Python,確保使用正確的代碼版本温眉,否則有些功能可能無法工作。

請注意有些新的 GDB 命令只有在 debug 需要的庫存在才能正常工作翁狐。

這個腳本在 Ubuntu 上面的 gcc 4.5.2 工作時类溢,會爆出錯誤No symbol "co" in current context.,是因為call_functionPyEval_EvalFrameExPyEval_EvalCodeEx 之間露懒。重新使用make "CFLAGS=-g -fno-inline -fno-strict-aliasing"編譯 Python 可以解決這個問題闯冷。

使用 Python Stack Traces GDB 腳本

在 gdb 命令行里,可以這樣查看 Python stack trace:

(gdb) pystack

同樣的懈词,可以獲取一列 stack frame 的 Python 變量:

(gdb) pystackv
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蛇耀,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子坎弯,更是在濱河造成了極大的恐慌纺涤,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件抠忘,死亡現(xiàn)場離奇詭異撩炊,居然都是意外死亡,警方通過查閱死者的電腦和手機崎脉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進店門拧咳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人囚灼,你說我怎么就攤上這事骆膝。” “怎么了灶体?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵阅签,是天一觀的道長。 經(jīng)常有香客問我蝎抽,道長愉择,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮锥涕,結果婚禮上衷戈,老公的妹妹穿的比我還像新娘。我一直安慰自己层坠,他們只是感情好殖妇,可當我...
    茶點故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著破花,像睡著了一般谦趣。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上座每,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天前鹅,我揣著相機與錄音,去河邊找鬼峭梳。 笑死舰绘,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的葱椭。 我是一名探鬼主播捂寿,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼孵运!你這毒婦竟也來了秦陋?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤治笨,失蹤者是張志新(化名)和其女友劉穎驳概,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體旷赖,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡抡句,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了杠愧。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片待榔。...
    茶點故事閱讀 38,747評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖流济,靈堂內(nèi)的尸體忽然破棺而出锐锣,到底是詐尸還是另有隱情,我是刑警寧澤绳瘟,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布雕憔,位于F島的核電站,受9級特大地震影響糖声,放射性物質(zhì)發(fā)生泄漏斤彼。R本人自食惡果不足惜分瘦,卻給世界環(huán)境...
    茶點故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望琉苇。 院中可真熱鬧嘲玫,春花似錦、人聲如沸并扇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽穷蛹。三九已至土陪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間肴熏,已是汗流浹背鬼雀。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蛙吏,地道東北人源哩。 一個月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像出刷,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子坯辩,可洞房花燭夜當晚...
    茶點故事閱讀 43,658評論 2 350