Python基礎(chǔ)教程之異常處理詳解
前言
最近發(fā)現(xiàn)有些東西長(zhǎng)時(shí)間不用就要忘了,堅(jiān)持每天復(fù)習(xí)總結(jié)一個(gè)小知識(shí)點(diǎn)吧~
異常是什么呢?就是在代碼執(zhí)行過(guò)程中非預(yù)期的執(zhí)行結(jié)果,隨著代碼越來(lái)越復(fù)雜,代碼中的執(zhí)行邏輯也會(huì)越來(lái)越復(fù)雜,如果沒(méi)有處理好異常情況,很有可能造成軟件執(zhí)行錯(cuò)誤,導(dǎo)致重大損失。相反,如果合理的處理異常情況,則可以增強(qiáng)軟件的穩(wěn)定性,提高體驗(yàn)感。
異常
在Python中,使用異常對(duì)象(exception object)來(lái)表示代碼執(zhí)行過(guò)程中所發(fā)生的異常情況,當(dāng)執(zhí)行程序爆出錯(cuò)誤的時(shí)候則會(huì)拋出異常。
如果沒(méi)有正確處理異常,則會(huì)終止運(yùn)行。
你可以想象一下,如果你在開(kāi)發(fā)一款產(chǎn)品時(shí),出現(xiàn)異常而不報(bào)告出發(fā)生異常的原因,是不是會(huì)很難受,也很難解決異常的問(wèn)題。
為了提高產(chǎn)品的穩(wěn)定性與靈活性,Python運(yùn)行開(kāi)發(fā)者捕捉并處理各類(lèi)異常,一般的內(nèi)部模塊報(bào)錯(cuò)如KeyError異常類(lèi)較為常見(jiàn),當(dāng)然也有很多其他的。
錯(cuò)誤與異常
簡(jiǎn)單了解下,Python將代碼執(zhí)行錯(cuò)誤分為兩類(lèi):語(yǔ)法錯(cuò)誤(syntax error)和異常(exception)。
語(yǔ)法錯(cuò)誤
首先,是語(yǔ)法錯(cuò)誤的問(wèn)題。字面可知,代碼解析錯(cuò)誤。
這種錯(cuò)誤通常出現(xiàn)在初學(xué)者,主要原因是所執(zhí)行的代碼不符合Python語(yǔ)法的規(guī)范,故會(huì)報(bào)出語(yǔ)法錯(cuò)誤導(dǎo)致code停機(jī)。
下面給出一個(gè)錯(cuò)誤示范:
>>> if for not in list(1,2,3,4)
File "<stdin>", line 1
if for not in list(1,2,3,4)
^
SyntaxError: invalid syntax
從上面的報(bào)錯(cuò)中可以知道是語(yǔ)法錯(cuò)誤,無(wú)效的語(yǔ)法。并且指出了錯(cuò)誤的地方在for的位置,很顯然if和for不能用在一起。
異常
異常則是在代碼執(zhí)行過(guò)程中發(fā)現(xiàn)的錯(cuò)誤,這是很難提前被發(fā)現(xiàn)的,即使代碼寫(xiě)的很規(guī)范標(biāo)準(zhǔn),但也可能會(huì)出現(xiàn)執(zhí)行異常的情況。
下面給出一個(gè)錯(cuò)誤示例。經(jīng)常被提到的是除數(shù)為0的情況,數(shù)學(xué)運(yùn)算中,0是不可以作為除數(shù)的,如果作為除數(shù)則會(huì)爆出異常。
>>> a = 5 / 0 Traceback (most recent call last): File "<stdin>", line 1, in <module> ZeroDivisionError: division by zero
很明顯報(bào)錯(cuò)指出0作為除數(shù)是不對(duì)的。
異常處理
當(dāng)我們了解了錯(cuò)誤和異常后,就得處理異常情況。對(duì)于語(yǔ)法錯(cuò)誤這種問(wèn)題多多練習(xí)即可避免,對(duì)于第二種異常,python給出了try-except語(yǔ)句來(lái)處理。
為了更清晰的解釋?zhuān)€是以上面的除數(shù)為0的情況作為例子,我們通過(guò)添加try-except語(yǔ)句捕捉并處理異常情況:
def division(x, y):
try:
return x / y
except ZeroDivisionError:
print("0不能作為除數(shù)?。?!")
然后我們?cè)僭趖erminal調(diào)用函數(shù)試試:
division(x=1, y=0)
輸出:
0不能作為除數(shù)?。?!
雖然我們的輸入是錯(cuò)誤的理論應(yīng)該報(bào)錯(cuò),但是并沒(méi)有報(bào)錯(cuò)而且還返回了一段話。
下面解釋一下try-except語(yǔ)句的工作原理:
- Try-except中的代碼會(huì)被正常執(zhí)行
- 如果沒(méi)有出現(xiàn)異常則跳過(guò)except代碼塊并結(jié)束try-except
- 如果try-except中的某一句代碼出現(xiàn)了問(wèn)題異常,剩余代碼停止執(zhí)行,如果出現(xiàn)的異常與except所指定的一致,則執(zhí)行except中的代碼塊,異常處理結(jié)束整個(gè)應(yīng)用程序繼續(xù)執(zhí)行
- 如果出現(xiàn)的異常與except中指定的不符合,那么則跳出try語(yǔ)句,程序繼續(xù)拋出異常并終止執(zhí)行代碼
當(dāng)然,我們寫(xiě)的代碼可能不止出現(xiàn)一種異常情況,我們可以將所有異常寫(xiě)在一個(gè)except語(yǔ)句中,如下所示:
except (RuntimeError, TypeError, NameError):pass
如果捕捉到異常列表中的任意一項(xiàng)異常表達(dá)式,則都會(huì)進(jìn)入except處理。
當(dāng)然,如果你想對(duì)每一種異常進(jìn)行單獨(dú)處理也可以一個(gè)一個(gè)的分開(kāi)進(jìn)行處理:
def passpass(x=1):
try:
return print(x+x)
except (RuntimeError, TypeError, NameError):
pass
except TypeError:
print('參數(shù)錯(cuò)誤啦~')
except NameError:
print('名稱(chēng)錯(cuò)誤啦~')
今天先到這里明兒再更,去跳繩了,哎,每天卷卷卷,老北京雞內(nèi)卷啊~(2022.4.20)
Python的異常類(lèi)型是可以繼承的, 我們?cè)诖藘H需知道,若except后指定的異常繼承自前面異常,由此后面的異常也會(huì)被捕捉到,示例如下:
class A(Exception):
pass
class B(A):
pass
class C(B):
pass
for cls in [A, B, C]:
try:
raise cls()
except C:
print('C')
except B:
print('B')
except A:
print('A')
則會(huì)輸出:
A
B
C
相反,如果把except的順序倒過(guò)來(lái),則只會(huì)輸出A,由于異常B和C都繼承來(lái)自A,由此在捕捉到B異常后則會(huì)終止:
class A(Exception):
pass
class B(A):
pass
class C(B):
pass
for cls in [A, B, C]:
try:
raise cls()
except A:
print('A')
except B:
print('B')
except C:
print('C')
輸出全為A:
A
A
A
如果所有異常都一一的提取出來(lái),這會(huì)很麻煩,此時(shí)可以在最后的一個(gè)except中不設(shè)置異常類(lèi)型,由此剩下沒(méi)有被捕獲的異常全會(huì)被捕捉:
def passpass(x=1):
try:
return print(x/x)
except TypeError:
print('參數(shù)錯(cuò)誤啦~')
except NameError:
print('名稱(chēng)錯(cuò)誤啦~')
except:
print('報(bào)錯(cuò)啦~自己查')
一個(gè)重要功能:else.
else語(yǔ)句則是用來(lái)執(zhí)行一些額外操作,如try代碼塊中執(zhí)行了一些文件操作,在else中可以釋放資源,else的語(yǔ)法格式如下:
try: pass except: pass else: pass
當(dāng)然我們還可以操作異常,如下:
def passpass(x=1):
try:
return print(x/x)
except TypeError as error:
print('參數(shù)錯(cuò)誤啦~', error)
except NameError:
print('名稱(chēng)錯(cuò)誤啦~')
except:
print('報(bào)錯(cuò)啦~自己查')
自主拋出異常
開(kāi)發(fā)者在平常的有些情況下并沒(méi)有執(zhí)行錯(cuò)誤,但是不符合設(shè)計(jì)邏輯,由此需要開(kāi)發(fā)者主動(dòng)拋出異常,這時(shí)我們需要使用raise語(yǔ)句拋出異常:
>>> raise NameError('HiThere')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: HiThere
自定義異常
Python內(nèi)置異常無(wú)法滿足開(kāi)發(fā)需求的時(shí)候,可以自定義異常。
自定義異常類(lèi)必須要直接或間接繼承自Exception類(lèi)。自定義異常類(lèi)可以像其他類(lèi)一樣做任何事情,但原則上要保持簡(jiǎn)潔,提高一些屬性即可。
class Error(Exception): """Base class for exception in this module.""" pass class InputError(Error): """Exception raised for errors in the input. Attributes: expression -- input expression in which the error occurred message -- explanation of the winerror """ def __init__(self, expression, message): self.expression = expression self.message = message
finally子句
else在代碼正常執(zhí)行后才會(huì)被執(zhí)行的代碼塊,但有些情況無(wú)論代碼塊是否出現(xiàn)異常都要執(zhí)行,則需要用到finally語(yǔ)句:
def passpass(x=1):
try:
return print(x/x)
except TypeError as error:
print('參數(shù)錯(cuò)誤啦~', error)
except NameError:
print('名稱(chēng)錯(cuò)誤啦~')
except:
print('報(bào)錯(cuò)啦~自己查')
finally:
print('運(yùn)算結(jié)束~')
總結(jié)
到此這篇關(guān)于Python基礎(chǔ)教程之異常處理的文章就介紹到這了,更多相關(guān)Python異常處理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python坐標(biāo)線性插值應(yīng)用實(shí)現(xiàn)
這篇文章主要介紹了Python坐標(biāo)線性插值應(yīng)用實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11
Python安全獲取域管理員權(quán)限幾種方式操作示例
在不考慮直接攻擊域控的情況下,如何快速獲取域管理員權(quán)限呢?本文分享幾種常見(jiàn)的獲取域管理員權(quán)限的方式,有需要的朋友可以借鑒參考下2021-10-10
opencv-python 提取sift特征并匹配的實(shí)例
今天小編就為大家分享一篇opencv-python 提取sift特征并匹配的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-12-12
python獲取文件版本信息、公司名和產(chǎn)品名的方法
這篇文章主要介紹了python獲取文件版本信息、公司名和產(chǎn)品名的方法,是Python程序設(shè)計(jì)中非常實(shí)用的技巧,需要的朋友可以參考下2014-10-10
pyhton列表轉(zhuǎn)換為數(shù)組的實(shí)例
下面小編就為大家分享一篇pyhton列表轉(zhuǎn)換為數(shù)組的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-04-04
詳解Python中的分支和循環(huán)結(jié)構(gòu)
這篇文章主要介紹了Python中的分支和循環(huán)結(jié)構(gòu),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-02-02
Python實(shí)現(xiàn)類(lèi)別變量的獨(dú)熱編碼
這篇文章主要為大家詳細(xì)介紹了基于Python下OneHotEncoder與pd.get_dummies兩種方法,實(shí)現(xiàn)機(jī)器學(xué)習(xí)中最優(yōu)的編碼方法——獨(dú)熱編碼的方法,需要的可以參考一下2023-02-02

