高級語言通常都內置了一套try...except...finally...的錯誤處理機制,Python也不例外。
try
用一個例子來看看try的機制
try:
print('try...')
r = 10 / 0
print('result:', r)
except ZeroDivisionError as e:
print('except:', e)
finally:
print('finally...')
print('END')
# 當我們認為某些代碼可能會出錯時,就可以用try來運行這段代碼,如果執行出錯,則后續代碼不會繼續執行,而是直接跳轉至錯誤處理代碼,即except語句塊,執行完except后,如果有finally語句塊,則執行finally語句塊,至此,執行完畢。
# 上面的代碼在計算10 / 0時會產生一個除法運算錯誤:
try...
except: division by zero
finally...
END
# 如果把除數0改成2,則執行結果如下:
try...
result: 5
finally...
END
# 錯誤應該有很多種類,如果發生了不同類型的錯誤,應該由不同的except語句塊處理。沒錯,可以有多個except來捕獲不同類型的錯誤:
try:
print('try...')
r = 10 / int('a')
print('result:', r)
except ValueError as e:
print('ValueError:', e)
except ZeroDivisionError as e:
print('ZeroDivisionError:', e)
finally:
print('finally...')
print('END')
# 如果沒有錯誤發生,可以在except語句塊后面加一個else,當沒有錯誤發生時,會自動執行else語句:
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')
# Python的錯誤其實也是class,所有的錯誤類型都繼承自BaseException,所以在使用except時需要注意的是,它不但捕獲該類型的錯誤,還把其子類也“一網打盡”。比如:
try:
foo()
except ValueError as e:
print('ValueError')
except UnicodeError as e:
print('UnicodeError')
# 第二個except永遠也捕獲不到UnicodeError,因為UnicodeError是ValueError的子類,如果有,也被第一個except給捕獲了。
# 使用try...except捕獲錯誤還有一個巨大的好處,就是可以跨越多層調用,比如函數main()調用foo(),foo()調用bar(),結果bar()出錯了,這時,只要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...')
# 也就是說,不需要在每個可能出錯的地方去捕獲錯誤,只要在合適的層次去捕獲錯誤就可以了。這樣一來,就大大減少了寫try...except...finally的麻煩。