學習目标:
python學習十二、
學習内容:
1、錯誤處理
2、調試
3、單元測試
4、文檔測試
1、錯誤處理
1、try
錯誤機制try
- 當錯誤發生時,後續語句print()不會被執行,except捕獲到ZeroDivisionError被執行,finally語句最後執行
try…
except:…
finally…
END
如果有finally,不管有沒有錯則一定會被執行(可以沒有finally語句)
- try的執行個體
在try機制中,as e意思是把錯誤資訊賦給e,是以列印e就能列印出錯誤資訊
lists = [1,2,3,4]
try:
print(lists[10])
except Exception as e:
print(e)
輸出:
list index out of range
except永遠也捕獲不到UnicodeError,因為UnicodeError是ValueError的子類,如果有,也被第一個except給捕獲了
try:
print('try...')
r = 10 / int('2')
print('result:', r)
except ValueError as e:
print('ValueError:', e)
except ZeroDivisionError as e:
print('ZeroDivisionError:', e)
except UnicodeError as e:
print('UnicodeError')
else:
print('no error!')
finally:
print('finally...')
print('END')
-
try…except跨層調用
try…except捕獲錯誤可以跨越多層調用
比如函數main()調用bar(),bar()調用foo(),結果foo()出錯了,隻要main()捕獲到了,就可以處理
def foo(s):
return 10 / int(s)
def bar(s):
return foo(s) * 2
def main():
try:
bar('0')
except Exception as e:
print('Error:', e)
finally:
print('finally...')
2、記錄錯誤
當我們找出錯誤時,就應該能把錯誤堆棧列印出來
Python内置的logging子產品可以非常容易地記錄錯誤資訊,同樣是出錯,但程式列印完錯誤資訊後會繼續執行,并正常退出
# err_logging.py
import logging
def foo(s):
return 10 / int(s)
def bar(s):
return foo(s) * 2
def main():
try:
bar('0')
except Exception as e:
logging.exception(e)
main()
print('END')
輸出:
ERROR:root:division by zero
Traceback (most recent call last):
File "F:/pycharm/project/ten.py", line 39, in main
bar('0')
File "F:/pycharm/project/ten.py", line 35, in bar
return foo(s) * 2
File "F:/pycharm/project/ten.py", line 32, in foo
return 10 / int(s)
ZeroDivisionError: division by zero
END
3、抛出錯誤
Python的内置函數會抛出很多類型的錯誤,一般情況下我們都是盡量調用Python的内置函數,也可以讓自己編寫的函數也可以抛出錯誤
用raise語句抛出一個錯誤的執行個體,raise語句如果不帶參數,就會把目前錯誤原樣抛出
class FooError(ValueError):
pass
def foo(s):
n = int(s)
if n==0:
raise FooError('invalid value: %s' % s)
return 10 / n
foo('0')
輸出:
Traceback (most recent call last):
File "F:/pycharm/project/ten.py", line 36, in <module>
foo('0')
File "F:/pycharm/project/ten.py", line 33, in foo
raise FooError('invalid value: %s' % s)
__main__.FooError: invalid value: 0
2、調試
1、斷言
凡是用print()來輔助檢視的地方,都可以用斷言(assert)來替代
在段言中,assert後面的語句應該成立,否則就輸出最後面的錯誤提示
斷言的開關“-O”是英文大寫字母O,不是數字0
def foo(s):
n = int(s)
assert n != 0, 'n is zero!'
return 10 / n
def main():
foo('0')
輸出:
Traceback (most recent call last):
...
AssertionError: n is zero!
2、logging
和assert比,logging不會抛出錯誤,而且可以輸出到檔案
- logging的好處,允許你指定記錄資訊的級别,指定level=INFO時,logging.debug就不起作用,指定level=WARNING後,debug和info就不起作用
- 日志等級從低到高的順序是: DEBUG < INFO < WARNING < ERROR < CRITICAL
- DEBUG:程式調試bug時使用
- INFO:程式正常運作時使用
- WARNING:程式未按預期運作時使用,但并不是錯誤,如:使用者登入密碼錯誤
- ERROR:程式出錯誤時使用,如:IO操作失敗
- CRITICAL:特别嚴重的問題,導緻程式不能再繼續運作時使用,如:磁盤空間為空,一般很少使 用
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 "F:/pycharm/project/ten.py", line 33, in <module>
print(10 / n)
ZeroDivisionError: division by zero