溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

python調(diào)試工具pdb怎么使用

發(fā)布時間:2022-11-08 09:48:48 來源:億速云 閱讀:306 作者:iii 欄目:編程語言

這篇文章主要講解了“python調(diào)試工具pdb怎么使用”,文中的講解內(nèi)容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“python調(diào)試工具pdb怎么使用”吧!

一、pdb 有2種用法

pdb:python debugger

1、非侵入式方法 (不用額外修改源代碼,在命令行下直接運行就能調(diào)試)

python3 -m pdb filename.py

2、侵入式方法 (需要在被調(diào)試的代碼中添加以下代碼然后再正常運行代碼)

import pdb pdb.set_trace()

當你在命令行看到下面這個提示符時,說明已經(jīng)正確打開了pdb

(Pdb)

二、pdb 基本命令

命令解釋
break 或 b設(shè)置斷點
continue 或 c繼續(xù)執(zhí)行程序
list 或 l查看當前行的代碼段
step 或 s進入函數(shù)(進入 for 循環(huán)用 next 而不是用 step)
return 或 r執(zhí)行代碼直到從當前函數(shù)返回
next 或 n執(zhí)行下一行
up 或 u返回到上個調(diào)用點(不是上一行)
p x打印變量x的值
exit 或 q中止調(diào)試,退出程序
help幫助

在實際使用中發(fā)現(xiàn),用shell腳本運行python文件時,可能無法用pdb調(diào)試,會退出。此時只能直接運行py文件來調(diào)試。

三、在指定文件的指定位置,用break命令設(shè)置斷點

3.1 在本文件中的指定位置設(shè)置斷點

比如下面的例子,要想進入到模型的 forward() 方法中查看前向傳播過程中的數(shù)據(jù)處理過程,只能在  forward() 的第一行(即26行)設(shè)置斷點,pdb.set_trace()

但有時候模型很復雜,用這種方法會導致程序報錯直接退出(我也不知道是什么原因),那么我們就可以考慮用 break 命令在這一行插入斷點,使得程序運行到 forward() 時就會停下來。

import torchimport torch.nn as nnimport pdbclass EncoderLayer(nn.Module):    def __init__(self):        super().__init__()
        self.conv1 = nn.Conv2d(4, 10, (3, 3))
        self.conv2 = nn.Conv2d(10, 4, (3, 3))
        self.relu = nn.ReLU()    def forward(self, x):
        x=self.relu(self.conv1(x))        return self.relu(self.conv2(x))class Encoder(nn.Module):    def __init__(self,num_layers):        super().__init__()        # encoders 由 num_layers個 EncoderLayer子層組成,每個子層結(jié)構(gòu)相同,但參數(shù)不一定相同。
        self.ModelList = nn.ModuleList([EncoderLayer() for _ in range(num_layers)])    def forward(self, x):        # ModuleList是一個list,只能通過list的操作方式(如用for循環(huán)、下標索引等)進行forward計算。
        for layer in self.ModelList:
            x = layer(x)        return xif __name__=="__main__":
    pdb.set_trace()   
    input = torch.rand(5, 4, 30, 30)
    model = Encoder(num_layers=4)
    output = model(input)

具體方法: (1)首先在前面的任意一行設(shè)置 pdb.set_trace() ,使得程序停下來。 (2)輸入 break 26 就可以了。如圖:

python調(diào)試工具pdb怎么使用這樣斷點就設(shè)置成功了,程序運行到forward()就會停下來。

這里的26是行數(shù),需要注意的是 斷點位置不能是注釋,比如我們在25行(注釋行)設(shè)置斷點,就會失敗:

python調(diào)試工具pdb怎么使用總結(jié)一下,在同一個文件中設(shè)置斷點的命令是:

break line

3.2 在其他文件中的指定位置設(shè)置斷點

如果想要設(shè)置的斷點不在初始運行文件里面呢,怎么在其他文件中用break命令設(shè)置斷點呢?我們看這個例子:

把3.1的代碼分為三個py文件,放下同一路徑下:

  ![在這里插入圖片描述](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4b5d476ba5b14b0ba541d78930b9704a~tplv-k3u1fbpfcp-zoom-1.image)

看一下每個文件的內(nèi)容:

run.py:

初始的 pdb.set_trace() 設(shè)置在run.py中。

import torchfrom encoder import Encoderimport pdbif __name__=="__main__":
    pdb.set_trace()    input = torch.rand(5, 4, 30, 30)
    model = Encoder(num_layers=4)
    output = model(input)

encoder.py:

from encoder_layer import EncoderLayerimport torch.nn as nnclass Encoder(nn.Module):    def __init__(self,num_layers):        super().__init__()        # encoders 由 num_layers個 EncoderLayer子層組成,每個子層結(jié)構(gòu)相同,但參數(shù)不一定相同。
        self.ModelList = nn.ModuleList([EncoderLayer() for _ in range(num_layers)])    def forward(self, x):        # ModuleList是一個list,只能通過list的操作方式(如用for循環(huán)、下標索引等)進行forward計算。
        for layer in self.ModelList:
            x = layer(x)        return x

encoder_layer.py:

import torch.nn as nnclass EncoderLayer(nn.Module):    def __init__(self):        super().__init__()
        self.conv1 = nn.Conv2d(4, 10, (3, 3))
        self.conv2 = nn.Conv2d(10, 4, (3, 3))
        self.relu = nn.ReLU()    def forward(self, x):
        x=self.relu(self.conv1(x))        return self.relu(self.conv2(x))

現(xiàn)在我們運行 run.py ,然后在 encoder.py 的第12行 設(shè)置斷點,即

for layer in self.ModelList:

命令為:

break encoder.py:12

即 break filename:linepython調(diào)試工具pdb怎么使用我們可以看到,程序可以從  output = model(input) 進入到 forward() 中:python調(diào)試工具pdb怎么使用這樣可以很方便地進行調(diào)試。

如果初始斷點與目標斷點不在同一個目錄下的文件中,也可以通過相對路徑下的文件名設(shè)置斷點,如:

(Pdb) break ../transformer/asr_model.py:91Breakpoint 1 at /local/wenet/examples/aishell/s0/wenet/transformer/asr_model.py:91(Pdb)

四、使用 pdb 時發(fā)現(xiàn)的問題

4.1 使用軟鏈接時,pdb 顯示的文件路徑與實際路徑不一致的問題

如圖可以發(fā)現(xiàn),pdb 有三行組成,第一行時文件路徑,第二行是當前執(zhí)行的代碼行,第三行是輸入命令行。

在存在軟鏈接時,pdb顯示的路徑是軟鏈接指向的路徑,但實際上的代碼路徑是拷貝了軟連接內(nèi)容的路徑,這兩個路徑不一樣,一定要注意。python調(diào)試工具pdb怎么使用

4.2 pdb有時候無法在模型的 forward() 方法中加入斷點

pdb有時候無法用 pdb.set_trace() 在模型的 forward() 方法中加入斷點,報錯內(nèi)容為:

Compiled functions can't take variable number of arguments or use keyword-only arguments with defaul

大概意思是 “編譯后的函數(shù)不能接受數(shù)量可變的參數(shù),也不能在default中使用僅關(guān)鍵字參數(shù)?!?/p>

不懂啥意思,這個問題也沒有解決。

五、程序奔潰后的事后調(diào)試:pdb.pm()

前面所述都是在程序開始運行時就插入斷點,用pdb進行調(diào)試,即事前調(diào)試。其實 pdb 還可以進行事后調(diào)試,即在程序有bug運行奔潰后用python調(diào)試器進行查看。

比如 test.py 顯然是有 bug 的:

# test.pydef add(n):    return n+1add("hello")

直接運行:

python test.py

程序奔潰:

F:\PycharmProjects\pytorch_practice>python test.py
Traceback (most recent call last):
  File "test.py", line 4, in <module>
    add("hello")
  File "test.py", line 2, in add
    return n+1
TypeError: can only concatenate str (not "int") to str

這樣我們是無法用pdb進行調(diào)試的。那么當程序崩潰后,我們該怎樣去調(diào)試呢?

我們可以用下面這個命令進行簡單調(diào)試:

python -i test.py

-i 選項可以讓程序結(jié)束后打開一個交互式shell,如下:

F:\PycharmProjects\pytorch_practice>python -i test.py
Traceback (most recent call last):
  File "test.py", line 4, in <module>
    add("hello")
  File "test.py", line 2, in add
    return n+1
TypeError: can only concatenate str (not "int") to str
>>>

現(xiàn)在我們發(fā)現(xiàn)程序結(jié)束后出現(xiàn)了 >>> 符號,這就是python調(diào)試器。

輸入命令:

import pdb pdb.pm()

其中 pdb.pm() 用于程序發(fā)生異常導致奔潰后的事后調(diào)試,可以跟蹤異常程序最后的堆在信息。

執(zhí)行命令后得到:

TypeError: can only concatenate str (not "int") to str
>>> import pdb
>>> pdb.pm()
> f:\pycharmprojects\pytorch_practice\test.py(2)add()
-> return n+1
(Pdb)

可以發(fā)現(xiàn),pdb.pm() 已經(jīng)追蹤到了導致程序奔潰的語句:return n+1

此時可以打印 n 的值進行檢查:

(Pdb) p n'hello'(Pdb) q>>> quit()

F:\PycharmProjects\pytorch_practice>

q 表示退出pdb調(diào)試,quit() 表示退出 python 調(diào)試器。

感謝各位的閱讀,以上就是“python調(diào)試工具pdb怎么使用”的內(nèi)容了,經(jīng)過本文的學習后,相信大家對python調(diào)試工具pdb怎么使用這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI