24. 錯誤、除錯和測試
阿新 • • 發佈:2020-08-28
try:
try:
print('try...')
r = 10 / 0
print('result:', r)
except ZeroDivisionError as e:
print('except:', e)
finally:
print('finally...')
print('END')
- 從輸出可以看到,當錯誤發生時,後續語句print('result:', r)不會被執行,except由於捕獲到ZeroDivisionError,因此被執行。最後,finally語句被執行。然後,程式繼續按照流程往下走。
- 由於沒有錯誤發生,所以except語句塊不會被執行,但是finally如果有,則一定會被執行(可以沒有finally語句)。
try:
print('try...')
r = 10 / int('2')
print('result:', r)
except ValueError as e:
print('ValueError:', e)
except ZeroDivisionError as e:
print('ZeroDivisionError:', e)
else:
print('no error!')
finally:
print('finally...')
print('END')
- 如果沒有錯誤發生,可以在except語句塊後面加一個else,當沒有錯誤發生時,會自動執行else語句。
呼叫堆疊
如果錯誤沒有被捕獲,它就會一直往上拋,最後被Python直譯器捕獲,列印一個錯誤資訊,然後程式退出。
捕獲錯誤的原因
如果不捕獲錯誤,自然可以讓Python直譯器來打印出錯誤堆疊,但程式也被結束了。既然我們能捕獲錯誤,就可以把錯誤堆疊打印出來,然後分析錯誤原因,同時,讓程式繼續執行下去。
丟擲錯誤
因為錯誤是class,捕獲一個錯誤就是捕獲到該class的一個例項。因此,錯誤並不是憑空產生的,而是有意建立並丟擲的。
# err_raise.py class FooError(ValueError): pass def foo(s): n = int(s) if n==0: raise FooError('invalid value: %s' % s) return 10 / n foo('0')
斷言
凡是用print()來輔助檢視的地方,都可以用斷言(assert)來替代。
程式中如果到處充斥著assert,和print()相比也好不到哪去。不過,啟動Python直譯器時可以用-O引數來關閉assert;關閉後,你可以把所有的assert語句當成pass來看。
logging
把print()替換為logging是第3種方式,和assert比,logging不會丟擲錯誤,而且可以輸出到檔案。
import logging
# logging.basicConfig(level=logging.INFO)
s = '0'
n = int(s)
logging.info('n = %d' % n)
232/531
print(10 / n)
-
logging.info()就可以輸出一段文字。執行,發現除了ZeroDivisionError,沒有任何資訊。
-
import logging之後新增一行配置後
$ python3 err.py INFO:root:n = 0 Traceback (most recent call last): File "err.py", line 8, in <module> print(10 / n) ZeroDivisionError: division by zero
logging的好處,它允許指定記錄資訊的級別,有debug,info,warning,error等幾個級別