Python 新手之旅 V1.10 - 單元 5 - Python 的測試、除錯與模組



互動式環境可以直接測試程式碼,如果有錯或無法執行的地方,也會直接停下來告訴我們,例如


>>> def do_something(a, b):
...    return a + b
...
>>> do_something(3, "3")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in do_something
TypeError: unsupported operand type(s) for +: 'int' and 'str'
>>>

當然這是個故意的錯誤,倒是簡單的示範簡單的函數 (function) 或類別 (class) 都可以直接放到互動式介面中測試,這就是互動式介面方便的地方。


互動式介面還有一個很大的優點,就是可以直接拿標準模組庫 (standard library) 的內容來測試或學習。例如以下 import 標準模組庫的 math 模組 (module)


>>> import math
>>> math.ceil(55.9801)
56
>>> math.factorial(12)
479001600
>>> math.log2(1024)
10.0
>>>

不過這可能僅限於小程式或測試相關程式碼的部分,就單一類別或函數或模組。當有需要組合多個函數或類別之時,最好把程式碼放到模組中,也就是副檔名為 .py 的檔案內。例如以下猜數字遊戲要猜 09 十個數字之一


001import random
002 
003answer = random.randint(0, 9)
004while True:
005    guess = input(":")
006    if guess == answer:
007        print("Right!!")
008        break
009    else:
010        print("Wrong!!")

假設程式碼在文字編輯器 (text editor) 中打好,我們就可以在命令列裡打指令執行,執行結果如下


$ python3 guessgame.py
:1
Wrong!!
:2
Wrong!!
:3
Wrong!!
:4
Wrong!!
:5
Wrong!!
:6
Wrong!!
:7
Wrong!!
:8
Wrong!!
:9
Wrong!!
:0
Wrong!!
:

09 每個數字都猜了,沒有一個數字是對的,因為程式中有個錯誤。我們暫時跳過不談這個錯誤,先切換到 IDE 中測試,以下為 PyCharm 的社群版



執行後,依序輸入 09 每個數字,結果一樣,我們點擊右上角蟲的圖示,開啟除錯模式看看



PyCharm 整合 pydev 這款式覺化的除錯器 (debugger)



重新執行以後結果一樣



PyCharm 也有些建議修改的選項,燈號出現就可以查看



錯誤共有三種,第一種是語法錯誤 (syntax errot) , IDE 或直譯器 (interpreter) 會直接挑出來,第二種是執行期間錯誤 (run-time error) ,這一類的錯誤也是由直譯器執行時挑出,或是藉由除錯工具或有除錯工具的 IDE 來分析,第三種也是最麻煩的一種叫做語意錯誤 (semantic error) ,如同這個猜數字程式,程式可以順利執行,卻得不到預期結果。


錯誤其實發生在第 6 行,迴圈 (loop) 的結束條件設定為如果 guess 等於 answer ,就印出 "Right!!" 然後跳出迴圈,隨之結束程式


006if guess == answer:

問題是 guess 永遠不會等於 answer ,原因很簡單,因為 answer 是整數型態,而 guess 利用 input() 從命令列擷取輸入,所以 guess 得到的是字串 (string) 而非整數 (integer) ,這裡拿字串跟整數做比較,自然永遠不會相等。


要讓迴圈順利結束有兩種方式,一種是把 answer 轉換為字串,或是把 guess 轉換為整數,這裡採用後者,第 6 行修改如下


006if int(guess) == answer:

重新執行就可順利結束



我們把猜數字遊戲的程式碼放在 guessgame.py 的檔案內,要知道一個 Python 程式就是一個模組,模組執行時所有未縮排的程式碼都會優先執行,所以如果這樣做


   import guessgame

引入的程式就會先執行猜數字遊戲一次,如果要避免被 import 後去執行未縮排的程式碼,此時可以把該為縮排的程式碼放在


   if __name__ == "__main__":

之後,這樣做為測試沒有縮排的程式碼就不會被執行了。


以上我們用很簡單只有幾行的猜數字遊戲示範測試、除錯等工作,開發大型程式時卻可能多達數百萬行程式碼,這時候需要把程式拆成許多的小單元分別進行測試,每個小單元都正確無誤後,再組合成完整的程式。


當模組越多,再來就是用資料夾(目錄)整理相關的模組,一個資料夾(目錄)中加入 __init__.py 就構成一個套件 (package) ,模組庫也就是用套件的方式來組織的。


the end


Python 新手之旅 V1.10 (Google Play)

沒有留言: