1. 程式人生 > >[基礎]-Python3 偵錯程式入門

[基礎]-Python3 偵錯程式入門

原文出處: Clément Verna   譯文出處:linux中國-Flowsnow   

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

Python 偵錯程式

Python 標準庫提供了一個名為 pdb 的偵錯程式。此偵錯程式提供了除錯所需的大多數功能,如斷點、單行步進、堆疊幀的檢查等等。

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

執行 pdb

執行 pdb 的最簡單方法是從命令列,將程式作為引數傳遞來除錯。 看看以下指令碼:

Python

 

1

2

3

4

5

6

7

8

9

10

# pdb_test.py

#!/usr/bin/python3

from time import sleep

def countdown(number):

    for i in range(number, 0, -1):

        print(i)

        sleep(1)

if __name__ == "__main__":

    seconds = 10

    countdown(seconds)

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

Python

 

1

2

3

4

$ python3 -m pdb pdb_test.py

> /tmp/pdb_test.py(1)<module>()

-> from time import sleep

(Pdb)

使用 pdb 的另一種方法是在程式中設定斷點。為此,請匯入 pdb 模組並使用set_trace 函式:

Python

 

1

2

3

4

5

6

7

8

9

10

11

# pdb_test.py

#!/usr/bin/python3

from time import sleep

def 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)

 

Python

 

1

2

3

4

$ python3 pdb_test.py

> /tmp/pdb_test.py(6)countdown()

-> print(i)

(Pdb)

指令碼在斷點處停止,pdb 顯示指令碼中的下一行。 你也可以在失敗後執行偵錯程式。 這稱為事後除錯postmortem debugging。

穿行於執行堆疊

除錯中的一個常見用例是在執行堆疊中穿行。 Python 偵錯程式執行後,可以使用以下命令:

  • w(here):顯示當前執行的行以及執行堆疊的位置。

 

Python

 

1

2

3

4

5

6

7

8

9

$ 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)

 

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

 

Python

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

$ python3 test_pdb.py

> /tmp/test_pdb.py(10)countdown()

-> print(i)

(Pdb) l

5

6

7     def countdown(number):

8         for i in range(number, 0, -1):

9             import pdb; pdb.set_trace()

10  ->         print(i)

11             sleep(1)

12

13

14     if __name__ == "__main__":

15         seconds = 10

 

  • u(p)/d(own):向上或向下穿行呼叫堆疊。

 

Python

 

1

2

3

4

5

6

7

8

9

10

$ 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)

 

單步執行程式

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

  • n(ext):繼續執行,直到達到當前函式中的下一行,或者返回
  • s(tep):執行當前行並在第一個可能的場合停止(在被呼叫的函式或當前函式中)
  • c(ontinue):繼續執行,僅在斷點處停止。

 

Python

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

$ py3 test_pdb.py

> /tmp/test_pdb.py(10)countdown()

-> print(i)

(Pdb) n

10

> /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) c

9

> /tmp/test_pdb.py(9)countdown()

-> import pdb; pdb.set_trace()

(Pdb)

該示例顯示了 next 和 step 之間的區別。 實際上,當使用 step 時,偵錯程式會進入 pdb 模組原始碼,而接下來就會執行 set_trace 函式。

檢查變數內容

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

 

Python

 

1

2

3

4

5

6

7

8

9

10

11

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) args

number = 10

(Pdb)

pdb 列印變數的值,在本例中是 10。

  • 可用於列印變數值的另一個命令是 p(rint)

 

Python

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

$ py3 test_pdb.py

> /tmp/test_pdb.py(10)countdown()

-> print(i)

(Pdb) list

5

6

7     def countdown(number):

8         for i in range(number, 0, -1):

9             import pdb; pdb.set_trace()

10  ->         print(i)

11             sleep(1)

12

13

14     if __name__ == "__main__":

15         seconds = 10

(Pdb) print(seconds)

10

(Pdb) p i

10

(Pdb) p number - i

0

(Pdb)

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

Python 文件包含每個 pdb 命令的參考和示例。 對於開始使用 Python 偵錯程式人來說,這是一個有用的讀物。

增強的偵錯程式

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

這些示例顯示如何在虛擬環境中安裝這兩個偵錯程式。 這些示例使用新的虛擬環境,但在除錯應用程式的情況下,應使用應用程式的虛擬環境。

安裝 IPython 的 ipdb

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

Python

 

1

2

3

$ python3 -m venv .test_pdb

$ source .test_pdb/bin/activate

(test_pdb)$ pip install ipdb

要在指令碼中呼叫 ipdb,必須使用以下命令。 請注意,該模組稱為 ipdb 而不是 pdb:

Python

 

1

import ipdb; ipdb.set_trace()

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

Python

 

1

$ sudo dnf install python3-ipdb

 

安裝 pdb++

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

Python

 

1

2

3

$ python3 -m venv .test_pdb

$ source .test_pdb/bin/activate

(test_pdb)$ pip install pdbp

pdb++ 重寫了 pdb 模組,因此你可以使用相同的語法在程式中新增斷點:

Python

 

1

import pdb; pdb.set_trace()

 

總結

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