程式設計師必備介面測試偵錯工具:
【相關推薦:Python3視訊教學 】
pdb:python debugger
1、非侵入式方法 (不用額外修改原始碼,在命令列下直接執行就能偵錯)
python3 -m pdb filename.py
2、侵入式方法 (需要在被偵錯的程式碼中新增以下程式碼然後再正常執行程式碼)
import pdb pdb.set_trace()
當你在命令列看到下面這個提示符時,說明已經正確開啟了pdb
(Pdb)
命令 | 解釋 |
---|---|
break 或 b | 設定斷點 |
continue 或 c | 繼續執行程式 |
list 或 l | 檢視當前行的程式碼段 |
step 或 s | 進入函數(進入 for 迴圈用 next 而不是用 step) |
return 或 r | 執行程式碼直到從當前函數返回 |
next 或 n | 執行下一行 |
up 或 u | 返回到上個呼叫點(不是上一行) |
p x | 列印變數x的值 |
exit 或 q | 中止偵錯,退出程式 |
help | 幫助 |
在實際使用中發現,用shell指令碼執行python檔案時,可能無法用pdb偵錯,會退出。此時只能直接執行py檔案來偵錯。
比如下面的例子,要想進入到模型的 forward() 方法中檢視前向傳播過程中的資料處理過程,只能在 forward() 的第一行(即26行)設定斷點,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子層組成,每個子層結構相同,但引數不一定相同。
self.ModelList = nn.ModuleList([EncoderLayer() for _ in range(num_layers)]) def forward(self, x): # ModuleList是一個list,只能通過list的操作方式(如用for迴圈、下標索引等)進行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)首先在前面的任意一行設定 pdb.set_trace() ,使得程式停下來。 (2)輸入 break 26 就可以了。如圖:
這樣斷點就設定成功了,程式執行到forward()就會停下來。
這裡的26是行數,需要注意的是 斷點位置不能是註釋,比如我們在25行(註釋行)設定斷點,就會失敗:
總結一下,在同一個檔案中設定斷點的命令是:
break line
如果想要設定的斷點不在初始執行檔案裡面呢,怎麼在其他檔案中用break命令設定斷點呢?我們看這個例子:
把3.1的程式碼分為三個py檔案,放下同一路徑下:
![在這裡插入圖片描述](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4b5d476ba5b14b0ba541d78930b9704a~tplv-k3u1fbpfcp-zoom-1.image)
登入後複製
看一下每個檔案的內容:
run.py:
初始的 pdb.set_trace() 設定在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子層組成,每個子層結構相同,但引數不一定相同。
self.ModelList = nn.ModuleList([EncoderLayer() for _ in range(num_layers)]) def forward(self, x): # ModuleList是一個list,只能通過list的操作方式(如用for迴圈、下標索引等)進行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))
登入後複製
現在我們執行 run.py ,然後在 encoder.py 的第12行 設定斷點,即
for layer in self.ModelList:
命令為:
break encoder.py:12
即 break filename:line我們可以看到,程式可以從 output = model(input) 進入到 forward() 中:這樣可以很方便地進行偵錯。
如果初始斷點與目標斷點不在同一個目錄下的檔案中,也可以通過相對路徑下的檔名設定斷點,如:
(Pdb) break ../transformer/asr_model.py:91Breakpoint 1 at /local/wenet/examples/aishell/s0/wenet/transformer/asr_model.py:91(Pdb)
登入後複製
如圖可以發現,pdb 有三行組成,第一行時檔案路徑,第二行是當前執行的程式碼行,第三行是輸入命令列。
在存在軟連結時,pdb顯示的路徑是軟連結指向的路徑,但實際上的程式碼路徑是拷貝了軟連線內容的路徑,這兩個路徑不一樣,一定要注意。
pdb有時候無法用 pdb.set_trace() 在模型的 forward() 方法中加入斷點,報錯內容為:
Compiled functions can't take variable number of arguments or use keyword-only arguments with defaul
大概意思是 「編譯後的函數不能接受數量可變的引數,也不能在default中使用僅關鍵字引數。」
不懂啥意思,這個問題也沒有解決。
前面所述都是在程式開始執行時就插入斷點,用pdb進行偵錯,即事前偵錯。其實 pdb 還可以進行事後偵錯,即在程式有bug執行奔潰後用python偵錯程式進行檢視。
比如 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進行偵錯的。那麼當程式崩潰後,我們該怎樣去偵錯呢?
我們可以用下面這個命令進行簡單偵錯:
python -i test.py
-i 選項可以讓程式結束後開啟一個互動式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
>>>
登入後複製
現在我們發現程式結束後出現了 >>> 符號,這就是python偵錯程式。
輸入命令:
import pdb pdb.pm()
其中 pdb.pm() 用於程式發生異常導致奔潰後的事後偵錯,可以跟蹤異常程式最後的堆在資訊。
執行命令後得到:
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)
登入後複製
可以發現,pdb.pm() 已經追蹤到了導致程式奔潰的語句:return n+1
此時可以列印 n 的值進行檢查:
(Pdb) p n'hello'(Pdb) q>>> quit()
F:\PycharmProjects\pytorch_practice>
登入後複製
q 表示退出pdb偵錯,quit() 表示退出 python 偵錯程式。
【相關推薦:Python3視訊教學 】
以上就是python偵錯工具pdb的用法彙總(Python Debugger)的詳細內容,更多請關注TW511.COM其它相關文章!