程序運(yùn)行的時候會因?yàn)槟撤N原因定枷,發(fā)生錯誤孤澎,導(dǎo)致程序不能運(yùn)行。發(fā)生錯誤時依鸥,Python你會創(chuàng)建一個異常對象亥至。我們需要在編寫代碼的時候,對異常的情況做處理。否則程序?qū)⑼V菇惆纾⒊霎a(chǎn)生一個回溯絮供,拋出錯誤信息。python內(nèi)置了一套異常處理機(jī)制茶敏。
1. 錯誤
錯誤一般分為語法錯誤和語義錯誤壤靶。
1.1 語法錯誤
語法錯誤(syntax errors)即代碼編寫不符合該語言的語法。一般由內(nèi)置的語法分析器檢測惊搏,并拋出異常贮乳。如下:缺少冒號時:
>>> for x in range(10)
... print(x)
...
File "<input>", line 1
for x in range(10)
^
SyntaxError: invalid syntax
1.2 語義錯誤
語義錯誤(又稱邏輯錯誤),一般是由于某種原因代碼輸出的結(jié)果不符合預(yù)期結(jié)果恬惯。此時就可能發(fā)生語義錯誤向拆。語義錯誤不能被立刻發(fā)現(xiàn)。如下:
>>> def average(x, y):
... return x + y / 2
...
該函數(shù)本意為求兩個數(shù)的平均數(shù)酪耳,由于運(yùn)算符優(yōu)先級問題浓恳,導(dǎo)致輸出結(jié)果偏離預(yù)期結(jié)果。
2. 異常
python使用異常對象來表示異常情況碗暗。程序發(fā)生錯誤時會引發(fā)一個異常颈将。若異常未被處理或捕捉,產(chǎn)生一個回溯(Traceback)言疗,拋出錯誤信息晴圾, 終止程序運(yùn)行≡胙伲回溯主要內(nèi)容解釋:
>>> 1 / 0
Traceback (most recent call last):
File "<input>", line 1, in <module> # 異常信息所在位置
ZeroDivisionError: division by zero # 異常類型及引起原因
python中的異常也是類死姚,相應(yīng)的異常對象就是該類的實(shí)例。python所有的異常類的基類均為BaseException梗醇。具體信息在這里知允。常見的異常類型如下:
2.1 異常處理
編寫代碼時,若我們知道某段代碼可能導(dǎo)致某種異常叙谨,又不希望程序以堆棧跟蹤的形式終止温鸽,可以使用try.....except.....finally的語句對異常進(jìn)行處理。
try語句后跟想要執(zhí)行的代碼手负,如果執(zhí)行出錯涤垫,則后續(xù)代碼不會繼續(xù)執(zhí)行,而是直接跳轉(zhuǎn)至錯誤處理代碼竟终,即except語句塊蝠猬,執(zhí)行完except后,如果有finally語句塊统捶,則執(zhí)行finally語句塊榆芦,至此柄粹,執(zhí)行完畢。
基本形式
捕捉異常的基本形式是try.........except..........語句
except語句的一般形式為:execpt 異常類型 as 變量: 異常處理語句
使用except時需要注意的是匆绣,它不但捕獲該類型的錯誤驻右,還捕捉子類異常。
# try--except---
try:
x = 10 / 0
peinr("x:", x)
except ZeroDivisionError as e:
print("error:%s" % e)
# 執(zhí)行結(jié)果
error:division by zero
捕獲多個異常
可以使用多個except語句來捕捉多個異常最多執(zhí)行一個崎淳。except子句后可跟一個元組堪夭,里面可包含多個異常類。
# 捕獲多個異常
try:
x = int(input("Enter x:"))
y = int(input("Enter y:"))
print(x / y)
except ZeroDivisionError as e:
print("error:%s" % e)
except ValueError as e:
print("error:%s" % e)
# 執(zhí)行結(jié)果
Enter x:10
Enter y:0
error:division by zero
捕獲未知異常
使用BaseException(所有異常類的父類)或Exception(大部分異常類的父類)來捕捉未知異常拣凹。使用except時需要注意的是森爽,它不但捕獲該類型的錯誤外盯,還捕捉子類異常宋彼。
# 捕獲未知異常
try:
x = 10 / 0
peinr("x:", x)
except Exception as e:
print("error:%s" % e)
# 執(zhí)行結(jié)果
error:division by zero
else子句
沒有異常發(fā)生時執(zhí)行else子句誊涯。
# else子句
try:
x = int(input("Enter x:"))
y = int(input("Enter y:"))
print(x / y)
except ZeroDivisionError as e:
print("error:%s" % e)
except ValueError as e:
print("error:%s" % e)
else:
print("沒有異常發(fā)生時執(zhí)行")
# 結(jié)果
Enter x:10
Enter y:2
5.0
沒有異常發(fā)生時執(zhí)行
finally子句
不管有沒有異常發(fā)生最終都執(zhí)行finally子句放坏。
# finally子句
try:
x = int(input("Enter x:"))
y = int(input("Enter y:"))
print(x / y)
except ZeroDivisionError as e:
print("error:%s" % e)
except ValueError as e:
print("error:%s" % e)
else:
print("沒有異常發(fā)生時執(zhí)行")
finally:
print("有無異常發(fā)生均執(zhí)行")
# 執(zhí)行結(jié)果
Enter x:10
Enter y:0
error:division by zero
有無異常發(fā)生均執(zhí)行
2.2 異常的傳遞性
- 異常的傳遞 —— 當(dāng) 函數(shù)/方法執(zhí)行出現(xiàn)異常,會將異常傳遞給函數(shù)/方法的調(diào)用一方
- 如果傳遞到主程序辛萍,仍然沒有異常處理儒搭,程序才會被終止
提示
- 在開發(fā)中悲柱,可以在主函數(shù)中增加異常捕獲
- 而在主函數(shù)中調(diào)用的其他函數(shù)捧请,只要出現(xiàn)異常,都會傳遞到主函數(shù)的 異常捕獲 中
- 這樣就不需要在代碼中棒搜,增加大量的異常捕獲疹蛉,能夠保證代碼的整潔
2.3 手動拋出異常
raise語句(即拋出一個異常的實(shí)例)。raise語句沒有參數(shù)就會將當(dāng)前異常原樣拋出力麸。我們可創(chuàng)建自定義的異常類可款,可直接或間接繼承自Exception類。
# 手動拋出異常
def input_password():
# 1. 提示用戶輸入密碼
pwd = input("請輸入密碼:")
# 2. 判斷密碼長度克蚂,如果長度 >= 8闺鲸,返回用戶輸入的密碼
if len(pwd) >= 8:
return pwd
# 3. 密碼長度不夠,需要拋出異常
# 1> 創(chuàng)建異常對象 - 使用異常的錯誤信息字符串作為參數(shù)
ex = Exception("密碼長度不夠")
# 2> 拋出異常對象
raise ex
try:
user_pwd = input_password()
print(user_pwd)
except Exception as result: # 捕獲異常
print("發(fā)現(xiàn)錯誤:%s" % result)
# 執(zhí)行結(jié)果
請輸入密碼:1653565
發(fā)現(xiàn)錯誤:密碼長度不夠
# 自定義異常類
class Myerror(ValueError):
pass
try:
x = int(input("Enter x:"))
y = int(input("Enter y:"))
print(x / y)
raise Myerror("自定義異常類的實(shí)例對象")
except Exception as e:
print(e)
# 執(zhí)行結(jié)果
Enter x:10
Enter y:2
5.0
自定義異常類的實(shí)例對象
3. 斷言
表示為一些布爾表達(dá)式埃叭,多用來對程序邏輯進(jìn)行檢測摸恍。常用在以下場合:
- 可以在預(yù)計(jì)正常情況下程序不會到達(dá)的地方放置斷言 :assert false
- 斷言可以用于檢查傳遞給私有方法的參數(shù)
- 使用斷言測試方法執(zhí)行的前置條件和后置條件
- 使用斷言檢查類的不變狀態(tài),確保任何情況下赤屋,某個變量的狀態(tài)必須滿足立镶。
- 單元測試等。
# 斷言
def add(x, y):
assert x > 5 # 用來判斷某種狀態(tài)
return x + y
result = add(3, 4)
print(result)