高級語言通常都內(nèi)置了一套try...except...finally...的錯誤處理機(jī)制拘央,Python也不例外涂屁。
try
用一個例子來看看try的機(jī)制
try:
print('try...')
r = 10 / 0
print('result:', r)
except ZeroDivisionError as e:
print('except:', e)
finally:
print('finally...')
print('END')
# 當(dāng)我們認(rèn)為某些代碼可能會出錯時,就可以用try來運(yùn)行這段代碼灰伟,如果執(zhí)行出錯拆又,則后續(xù)代碼不會繼續(xù)執(zhí)行,而是直接跳轉(zhuǎn)至錯誤處理代碼栏账,即except語句塊帖族,執(zhí)行完except后,如果有finally語句塊挡爵,則執(zhí)行finally語句塊盟萨,至此,執(zhí)行完畢了讨。
# 上面的代碼在計算10 / 0時會產(chǎn)生一個除法運(yùn)算錯誤:
try...
except: division by zero
finally...
END
# 如果把除數(shù)0改成2捻激,則執(zhí)行結(jié)果如下:
try...
result: 5
finally...
END
# 錯誤應(yīng)該有很多種類,如果發(fā)生了不同類型的錯誤前计,應(yīng)該由不同的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')
# 如果沒有錯誤發(fā)生男杈,可以在except語句塊后面加一個else丈屹,當(dāng)沒有錯誤發(fā)生時,會自動執(zhí)行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的錯誤其實(shí)也是class,所有的錯誤類型都繼承自BaseException旺垒,所以在使用except時需要注意的是彩库,它不但捕獲該類型的錯誤,還把其子類也“一網(wǎng)打盡”先蒋。比如:
try:
foo()
except ValueError as e:
print('ValueError')
except UnicodeError as e:
print('UnicodeError')
# 第二個except永遠(yuǎn)也捕獲不到UnicodeError骇钦,因為UnicodeError是ValueError的子類,如果有竞漾,也被第一個except給捕獲了眯搭。
# 使用try...except捕獲錯誤還有一個巨大的好處,就是可以跨越多層調(diào)用业岁,比如函數(shù)main()調(diào)用foo()鳞仙,foo()調(diào)用bar(),結(jié)果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的麻煩。