天天看點

python錯誤處理(錯誤處理、調試)學習目标:python學習十二、學習内容:

學習目标:

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
           

3、單元測試