Python Debug:用 GDB 來 Debug Python!

Python Debug 的方法很多種
但你有試過用 GDB Debug Python 嗎?
Python Debug
平常在寫 Python 的程式時,你都怎麼 Debug 的?
使用 “無限 Print 大法”? PDB? 還是使用 “通靈之術”? 亦或是找 ChatGPT 求助?
這些方法都很不錯,但有時候程式卡在某個 function 出不去,你想要看看目前程式內部的數值
這時候你可以試試看以下介紹的方法~
Example
這邊以一個簡單的 Python 程式作範例:
def binary_search(arr: list[int], start: int, end: int, target: int):
while start <= end:
mid = (end - start) // 2 + start
if arr[mid] == target:
return mid
elif arr[mid] < target:
start = mid
else:
end = mid
arr = [1,3,6,7,9,14,16,18,20]
target = 20
idx = binary_search(arr, 0, len(arr) - 1, 20)
print(f"{target} is at index {idx}")
並將他運行起來
python3 test.py
你會發現程式卡住了,久久都停不下來,我們來試試看新方法吧~
GDB
由於目前最廣泛使用的 Python 直譯器是由 C 實作的,所以我們可以使用 GDB 來幫助我們除錯
要使用 GDB 之前,我們要先安裝 GDB (如果你還沒安裝的話)
sudo apt install gdb
我們都知道,我們平常撰寫的是 Python 腳本,透過 Python Interpreter 來讀取腳本執行裡所寫的內容
所以我們要讓 GDB 偵錯的對象就是 python3
,另外我們需要給上正在運行的 python3
的 pid
我們可以透過指令查詢目標程式的 pid
ps aux | grep python3

ps aux | grep python3
查詢完後執行 GDB,pid 需要替換成自己查詢到的 pid,上方範例的 pid 為 4117
gdb python3 <pid>
這時,目標的程式就停止了,我們可以看到當前正在執行的函式是什麼

也可以列出目前的 call stack

但你會發現,這些都是 Python 內部的函式,根本看不懂是什麼,還有一堆的 ??
這時候你就會需要 Python GDB 擴充功能
Python GDB
我們先安裝 python3-dbg
來將 CPython 直譯器資訊新增到 GDB 上
sudo apt install python3-dbg
之後重複上節的操作,我們進入到 GDB 內部,我們就可以使用擴充功能的指令:
- py-list
- py-up / py-down
- py-bt
- py-print
- py-locals
py-list
列出當前執行的程式碼段落,正在執行的行前面有 >

py-list
py-up / py-down
切換執行的 frame,類似 GDB 的 up 和 down

py-up / py-down
py-bt
印出目前的 call stack

py-bt
py-print
印出某個變數的數值

py-print
py-locals
印出目前 frame 內的區域變數數值

py-locals
Core File
如果你不想影響到目前的程式運行,你可以產生完 core file 然後繼續讓他跑
在 GDB 內部輸入 generate-core-file,接著會產生 core file,我們就可以關閉 GDB 了

後續如果我們要讀取 core file 可以用以下的指令,就可以用當時的環境來 debug 了
gdb python3 <core file>
Reference
- https://docs.python.org/zh-tw/dev/howto/gdb_helpers.html
- https://blog.csdn.net/haima1998/article/details/89962435
如果你覺得這篇文章有用 可以考慮贊助飲料給大貓咪