Python 調試器入門

Python 生態系統包含豐富的工具和庫,可以讓開發人員更加舒適。 例如,我們之前已經介紹瞭如何使用交互式 shell 增強 Python。本文重點介紹另一種可以節省時間並提高 Python 技能的工具:Python 調試器。

Python 調試器

Python 標準庫提供了一個名為 pdb 的調試器。此調試器提供了調試所需的大多數功能,如斷點、單行步進、堆棧幀的檢查等等。

瞭解一些pdb 的基本知識很有用,因為它是標準庫的一部分。 你可以在無法安裝其他增強的調試器的環境中使用它。

運行 pdb

運行 pdb 的最簡單方法是從命令行,將程序作為參數傳遞來調試。 看看以下腳本:

# pdb_test.py#!/usr/bin/python3from time import sleepdef countdown(number): for i in range(number, 0, -1): print(i) sleep(1)if __name__ == "__main__": seconds = 10 countdown(seconds)

你可以從命令行運行 pdb,如下所示:

$ python3 -m pdb pdb_test.py> /tmp/pdb_test.py(1)<module>()-> from time
import sleep(Pdb)/<module>

使用 pdb 的另一種方法是在程序中設置斷點。為此,請導入 pdb 模塊並使用set_trace 函數:

# pdb_test.py#!/usr/bin/python3from time import sleepdef countdown(number): for i in range(number, 0, -1): import pdb; pdb.set_trace() print(i) sleep(1)if __name__ == "__main__": seconds = 10 countdown(seconds)$ python3 pdb_test.py> /tmp/pdb_test.py(6)countdown()-> print(i)(Pdb)

腳本在斷點處停止,pdb 顯示腳本中的下一行。 你也可以在失敗後執行調試器。 這稱為事後調試postmortem debugging。

穿行於執行堆棧

調試中的一個常見用例是在執行堆棧中穿行。 Python 調試器運行後,可以使用以下命令:

  • w(here):顯示當前執行的行以及執行堆棧的位置。
$ python3 test_pdb.py> /tmp/test_pdb.py(10)countdown()-> print(i)(Pdb) w/tmp/test_pdb.py(16)<module>()-> countdown(seconds)> /tmp/test_pdb.py(10)countdown()-> print(i)(Pdb)/<module>

l(ist):顯示當前位置周圍更多的上下文(代碼)

$ python3 test_pdb.py> /tmp/test_pdb.py(10)countdown()-> print(i)(Pdb) l567 def countdown(number):8 for i in range(number, 0, -1):9 import pdb; pdb.set_trace()10 -> print(i)11 sleep(1)121314 if __name__ == "__main__":15 seconds = 10

u(p)/d(own):向上或向下穿行調用堆棧。

$ py3 test_pdb.py> /tmp/test_pdb.py(10)countdown()-> print(i)(Pdb) up> /tmp/test_pdb.py(16)<module>()-> countdown(seconds)(Pdb) down> /tmp/test_pdb.py(10)countdown()-> print(i)(Pdb)/<module>

單步執行程序

pdb提供以下命令來執行和單步執行代碼:

  • n(ext):繼續執行,直到達到當前函數中的下一行,或者返回
  • s(tep):執行當前行並在第一個可能的場合停止(在被調用的函數或當前函數中)
  • c(ontinue):繼續執行,僅在斷點處停止。
$ py3 test_pdb.py> /tmp/test_pdb.py(10)countdown()-> print(i)(Pdb) n10> /tmp/test_pdb.py(11)countdown()-> sleep(1)(Pdb) n> /tmp/test_pdb.py(8)countdown()-> for i in range(number, 0, -1):(Pdb) n> /tmp/test_pdb.py(9)countdown()-> import pdb; pdb.set_trace()(Pdb) s--Call--> /usr/lib64/python3.6/pdb.py(1584)set_trace()-> def set_trace():(Pdb) c> /tmp/test_pdb.py(10)countdown()-> print(i)(Pdb) c9> /tmp/test_pdb.py(9)countdown()-> import pdb; pdb.set_trace()(Pdb)

該示例顯示了 next 和 step 之間的區別。 實際上,當使用 step 時,調試器會進入 pdb 模塊源代碼,而接下來就會執行 set_trace 函數。

檢查變量內容

pdb 非常有用的地方是檢查執行堆棧中存儲的變量的內容。 例如,a(rgs) 命令打印當前函數的變量,如下所示:

py3 test_pdb.py> /tmp/test_pdb.py(10)countdown()-> print(i)(Pdb) where/tmp/test_pdb.py(16)<module>()-> countdown(seconds)> /tmp/test_pdb.py(10)countdown()-> print(i)(Pdb) argsnumber = 10(Pdb)/<module>

pdb 打印變量的值,在本例中是 10。

可用於打印變量值的另一個命令是 p(rint)。

$ py3 test_pdb.py> /tmp/test_pdb.py(10)countdown()-> print(i)(Pdb) list567 def countdown(number):8 for i in range(number, 0, -1):9 import pdb; pdb.set_trace()10 -> print(i)11 sleep(1)121314 if __name__ == "__main__":15 seconds = 10(Pdb) print(seconds)10(Pdb) p i10(Pdb) p number - i0(Pdb)

如示例中最後的命令所示,print 可以在顯示結果之前計算表達式。

Python 文檔包含每個 pdb 命令的參考和示例。 對於開始使用 Python 調試器人來說,這是一個有用的讀物。

增強的調試器

一些增強的調試器提供了更好的用戶體驗。 大多數為 pdb 添加了有用的額外功能,例如語法突出高亮、更好的回溯和自省。 流行的增強調試器包括 IPython 的 ipdb 和 pdb++。

這些示例顯示如何在虛擬環境中安裝這兩個調試器。 這些示例使用新的虛擬環境,但在調試應用程序的情況下,應使用應用程序的虛擬環境。

安裝 IPython 的 ipdb

要安裝 IPython ipdb,請在虛擬環境中使用 pip:

$ python3 -m venv .test_pdb$ source .test_pdb/bin/activate(test_pdb)$ pip install ipdb

要在腳本中調用 ipdb,必須使用以下命令。 請注意,該模塊稱為 ipdb 而不是 pdb:

import ipdb; ipdb.set_trace()

IPython 的 ipdb 也可以用 Fedora 包安裝,所以你可以使用 Fedora 的包管理器 dnf 來安裝它:

$ sudo dnf install python3-ipdb

安裝 pdb++

你可以類似地安裝 pdb++:

$ python3 -m venv .test_pdb$ source .test_pdb/bin/activate(test_pdb)$ pip install pdbp

pdb++ 重寫了 pdb 模塊,因此你可以使用相同的語法在程序中添加斷點:

import pdb; pdb.set_trace()

總結

學習如何使用 Python 調試器可以節省你在排查應用程序問題時的時間。 對於瞭解應用程序或某些庫的複雜部分如何工作也是有用的,從而提高 Python 開發人員的技能。


分享到:


相關文章: