python的調試

調試

程序能一次寫完並正常執行的機率很小。總會有各類各樣的bug須要修正。
有的bug很簡單,看看錯誤信息就知道,有的bug很複雜,咱們須要知道出錯時
哪些變量的值是正確的,哪些變量的值是錯誤的,所以,須要一整套調試程序的手段來修復bug。

第一種方法:print
簡單直接粗暴有效,就是用print()把可能有問題的變量打印出來看看:

def foo(s):
    n = int(s)
    print(">>>n = %d" % n)
    return 10 / n

def main():
    foo("0")

main()

輸出結果:

>>>n = 0
Traceback (most recent call last):
  File "C:/Python36/test.py", line 9, in <module>
    main()
  File "C:/Python36/test.py", line 7, in main
    foo("0")
  File "C:/Python36/test.py", line 4, in foo
    return 10 / n
ZeroDivisionError: division by zero

用print()最大的壞處是未來還得刪除它,想一想程序裏處處都是print(),運行結果也會包含不少垃圾信息。
因此,咱們又有第二種方法。


第二種方法:斷言

凡是用print()來輔助查看的地方,均可以用斷言(assert)來代替:
def foo(s):
    n =  int(s)
    assert n != 0, "n is zero!"
    return 10 / n

def main():
    foo("0")

main()

assert的意思是,表達式 n!=0 應該是True,不然根據程序運行的邏輯,後面的代碼確定會出錯。
若是斷言失敗,assert語句自己就會拋出AssertionError:

Traceback (most recent call last):
  File "C:/Python36/test.py", line 9, in <module>
    main()
  File "C:/Python36/test.py", line 7, in main
    foo("0")
  File "C:/Python36/test.py", line 3, in foo
    assert n != 0, "n is zero!"
AssertionError: n is zero!

若是程序中處處充斥着assert,和print()相比也好不到哪去。
不過啓動python解釋器能夠用-o參數來關閉assert:
$ python3 -O err.py
Traceback (most recent call last):
  ...
ZeroDivisionError: division by zero

關閉後,你能夠把全部的assert語句當成pas來看。


第三種方法:logging
把print()替換爲logging是第三種方式,和assert比,logging不會拋出錯誤,並且能夠輸出到文件。

import logging

s = "0"
n = int(s)
logging.info("n = %d" % n)
print(10 / n)

輸出結果:
Traceback (most recent call last):
  File "C:/Python36/test.py", line 6, in <module>
    print(10 / n)
ZeroDivisionError: division by zero
>>>

logging.info()就能夠輸出一段文本。
運行,發現除了ZeroDivisionError, 沒有任何信息。 怎麼回事呢?

別急,在import logging 以後添加一行配置再試試
import logging
logging.basicConfig(level = logging.INFO)

s = "0"
n = int(s)
logging.info("n = %d" % n)
print(10 / n)

輸出結果:
INFO:root:n = 0
Traceback (most recent call last):
  File "C:/Python36/test.py", line 7, in <module>
    print(10 / n)
ZeroDivisionError: division by zero

看到輸出了吧,這就是使用logging的好處,它容許你指定記錄信息的級別
有debug,info,warning,error等幾個級別。
當咱們指定level = INFO時,logging.debug就不起做用了。
同理,指定level = WAENING後,debug和info就不起做用了。
這樣一來,擬具能夠放心地除數不一樣級別的I想你,也不用刪除,最後統一控制輸出哪一個級別的信息。
logging的另外一個好處就是經過簡單的配置,一條語句能夠同時輸出到不一樣的地方,好比console和文件。


第四種方法:pdb
第四種方式是移動python的調試器pdb,讓程序以單步方式運行,能夠隨時查看運行狀態。
咱們先來準備好程序:

s = "0"
n = int(s)
print(10 / n)

$ python3 -m pdb err.py
> /Users/michael/Github/learn-python3/samples/debug/err.py(2)<module>()
-> s = '0'

而後逐行輸入代碼檢查。
這種經過pdb在命令行調試的方法理論上是萬能的,可是實在太麻煩了。

IDE

若是要比較爽地設置斷點、單步執行,就須要一個支持調試功能的IDE。目前比較好的Python IDE有PyCharm:

http://www.jetbrains.com/pycharm/

另外,Eclipse加上pydev插件也能夠調試Python程序。


總結:

寫程序最痛苦的事情莫過於調試,程序每每會以你意想不到的流程來運行,你期待執行的語句其實根本沒有執行,這時候,就須要調試了。

雖然用IDE調試起來比較方便,可是最後你會發現,logging纔是終極武器。
相關文章
相關標籤/搜索