天天看點

python打錯了怎麼辦_python之錯誤調試

無論誰寫的程式,必定會存在bug,解決bug需要我們去調試程式。于是乎,在Python中,就會好幾種調試手段,如print、assert、logging、pdb、pdb.set_trace()

一、使用print()函數直接列印

>>> deffoo(s):

... n=int(s)

...print(n)

...return 10 /n

...>>> defmain():

... foo('0')

...>>>main()

Traceback (most recent call last):

File"", line 1, in File"", line 2, inmain

File"", line 4, infoo

ZeroDivisionError: division by zero

我們可以在認為可能出錯的地方列印變量,但這有很大的弊端,因為列印的代碼沒有實際功能,都是垃圾資訊。而且print最後還得删除,是以第二種方法是用assert替代print

二、使用斷言assert

>>> deffoo(s):

... n=int(s)

...assert n != 0,'n的值是0!'...return 10 /n

...>>> defmain():

... foo('0')

...>>>main()

Traceback (most recent call last):

File"", line 1, in File"", line 2, inmain

File"", line 3, infoo

AssertionError: n的值是0!

assert的意思,當後面的表達式為False時,就會抛出AssertionError,如果為True,什麼都不做,直接到下一行。assert有一大特性:在啟動python解釋器的時候可以使用-O參數來關閉assert(大寫的o)

PS E:\Python3.6.3\workspace> python -O err_assert.py

Traceback (most recent call last):

File"err_assert.py", line 9, in main()

File"err_assert.py", line 7, inmain

foo('0')

File"err_assert.py", line 4, infooreturn 10 /n

ZeroDivisionError: division by zer

三、使用logging

importlogging

logging.basicConfig(level=logging.INFO)

s= '0'n=int(s)

logging.info('n=%d' %n)print(10/n)#執行結果

PS E:\Python3.6.3\workspace>python err_logginginfo.py

INFO:root:n=0

Traceback (most recent call last):

File"err_logginginfo.py", line 6, in

print(10/n)

ZeroDivisionError: division by zero

使用logging不會抛出錯誤,直接輸出到檔案中。logging可以允許你指定記錄資訊的級别,級别由低到高分别是debug、info、warning、error、CRITICAL等級别,當定義進階别的時候,低級别的資訊不會輸出,這是把日志資訊輸出到控制台console,我們還可以通過設定把日志輸出到檔案中

四、使用python的調試器pdb

可以讓程式以單步方式執行,友善我們随時檢視運作狀态

建立程式err_pdb.py

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

然後以pdb模式啟動

PS E:\Python3.6.3\workspace> python -m pdb err_pdb.py> e:\python3.6.3\workspace\err_pdb.py(1)()-> s = '0'(Pdb) l1 -> s = '0'

2 n =int(s)3 print(10 /n)

[EOF]

(Pdb) n> e:\python3.6.3\workspace\err_pdb.py(2)()-> n =int(s)

(Pdb) p s'0'(Pdb) p n*** NameError: name 'n' is notdefined

(Pdb) n> e:\python3.6.3\workspace\err_pdb.py(3)()-> print(10 /n)

(Pdb) p n

(Pdb) p s'0'(Pdb) n

ZeroDivisionError: division by zero> e:\python3.6.3\workspace\err_pdb.py(3)()-> print(10 /n)

(Pdb) n--Return--

> e:\python3.6.3\workspace\err_pdb.py(3)()->None-> print(10 /n)

(Pdb) n

ZeroDivisionError: division by zero> (1)()->None

(Pdb) n--Return--

> (1)()->None

(Pdb) n

Traceback (most recent call last):

File"E:\Python3.6.3\lib\pdb.py", line 1667, inmain

pdb._runscript(mainpyfile)

File"E:\Python3.6.3\lib\pdb.py", line 1548, in_runscript

self.run(statement)

File"E:\Python3.6.3\lib\bdb.py", line 431, inrunexec(cmd, globals, locals)

File"", line 1, in File"e:\python3.6.3\workspace\err_pdb.py", line 3, in

print(10 /n)

ZeroDivisionError: division by zero

Uncaught exception. Entering post mortem debugging

Running'cont' or 'step'will restart the program> e:\python3.6.3\workspace\err_pdb.py(3)()->None-> print(10 /n)

(Pdb) q

Post mortem debugger finished. The err_pdb.py will be restarted> e:\python3.6.3\workspace\err_pdb.py(1)()-> s = '0'(Pdb) n> e:\python3.6.3\workspace\err_pdb.py(2)()-> n =int(s)

(Pdb) q

PS E:\Python3.6.3\workspace>

小寫字母l,可以列出所有要執行的代碼;

n 指令表示單步執行代碼;

p 後面加上變量名,可以随時檢視變量的值;

在pdb模式中,對于還沒有單步執行到的代碼,相關的變量的變更是無效的;

q 指令退出目前調試,進入重新從頭開始調試,再次輸入q,就會推出調試程式。

這種方式的調試,有一個弊端,就是隻能一步一步的執行下去,如果程式有很多行,豈不是累死。

五、使用pdb.set_trace()

#err_pdb.py

importpdb

s= '0'n=int(s)

pdb.set_trace()#程式運作到這裡會自動停止,等待指令

print(10 / n)

我們可以使用l、c、n、p、q等指令來控制和檢視程式

PS E:\Python3.6.3\workspace>python err_pdb.py> e:\python3.6.3\workspace\err_pdb.py(7)()-> print(10 /n)

(Pdb) p s'0'(Pdb) l2 importpdb3

4 s = '0'

5 n =int(s)6 pdb.set_trace() #程式運作到這裡會自動停止,等待指令

7 -> print(10 /n)

[EOF]

(Pdb) n

ZeroDivisionError: division by zero> e:\python3.6.3\workspace\err_pdb.py(7)()-> print(10 /n)

(Pdb) c

Traceback (most recent call last):

File"err_pdb.py", line 7, in

print(10 /n)

ZeroDivisionError: division by zero