python實(shí)用教程第九章異常處理課件_第1頁(yè)
python實(shí)用教程第九章異常處理課件_第2頁(yè)
python實(shí)用教程第九章異常處理課件_第3頁(yè)
python實(shí)用教程第九章異常處理課件_第4頁(yè)
python實(shí)用教程第九章異常處理課件_第5頁(yè)
已閱讀5頁(yè),還剩22頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、第九章 異常處理前面章節(jié)很多程序的執(zhí)行中,經(jīng)常會(huì)碰到程序執(zhí)行過(guò)程中沒(méi)有得到預(yù)期結(jié)果的情況。對(duì)于程序運(yùn)行過(guò)程中出現(xiàn)的不正常,有時(shí)稱(chēng)為錯(cuò)誤,有時(shí)稱(chēng)為異常,也有時(shí)說(shuō)程序沒(méi)有按預(yù)期運(yùn)行,從本章開(kāi)始將有一個(gè)統(tǒng)一的稱(chēng)謂異常。本章將帶領(lǐng)讀者學(xué)習(xí)如何處理各種異常,以及創(chuàng)建和自定義異常。Python快樂(lè)學(xué)習(xí)班的同學(xué)參觀完對(duì)象動(dòng)物園后,由導(dǎo)游帶領(lǐng)來(lái)到了異常過(guò)山車(chē)入口。此處的異常過(guò)山車(chē)坐起來(lái)非常刺激,乘坐異常過(guò)山車(chē)的過(guò)程中,過(guò)山車(chē)隨時(shí)都可能停下來(lái),有一些是正常的停止,也會(huì)有一些在未預(yù)知的情況下停止,但只要過(guò)山車(chē)上的乘客發(fā)揮自己的聰明才智,就有辦法讓停止的過(guò)山車(chē)動(dòng)起來(lái)。聽(tīng)起來(lái)很刺激吧,現(xiàn)在開(kāi)始開(kāi)啟異常過(guò)山車(chē)之旅。第1

2、頁(yè),共27頁(yè)。9.1 異常定義在本節(jié)開(kāi)始之前,先看看如下程序: print(hello,world)Traceback(most recent call last): File , line 1, in print(hello,world)NameError: name hello is not defined對(duì)于Python初學(xué)者,在Python的學(xué)習(xí)過(guò)程中,當(dāng)編寫(xiě)的代碼執(zhí)行時(shí),經(jīng)常會(huì)遇到程序執(zhí)行報(bào)錯(cuò)的問(wèn)題,使程序不能得到預(yù)期結(jié)果,如NameError、SyntaxError、TypeError、ValueError等,這些都是異常。這節(jié)我們會(huì)專(zhuān)門(mén)介紹異常。第2頁(yè),共27頁(yè)。異常是一個(gè)事件,

3、該事件會(huì)在程序執(zhí)行過(guò)程中發(fā)生,影響程序的正常執(zhí)行。一般情況下,在Python無(wú)法正常處理程序時(shí)就會(huì)發(fā)生異常。異常是Python的對(duì)象,表示一個(gè)錯(cuò)誤。當(dāng)Python腳本發(fā)生異常時(shí),需要捕獲并處理所有異常,否則程序會(huì)終止執(zhí)行。就如乘坐過(guò)山車(chē),有任何讓過(guò)山車(chē)在運(yùn)行過(guò)程中停下的異常因素都需要排除,否則難以保證乘客的安全。在Python中,異常屬于類(lèi)的實(shí)例,這些實(shí)例可以被引用,并且可以用很多種方法進(jìn)行捕捉,使得異常可以用一些友好的方式進(jìn)行化解,而不是簡(jiǎn)單粗暴的讓整個(gè)程序停止。第3頁(yè),共27頁(yè)。9.2 異?;獬隽水惓T趺崔k呢?就如乘坐的異常過(guò)山車(chē),當(dāng)在運(yùn)行過(guò)程中停止時(shí),乘客可以通過(guò)自己的才智讓過(guò)山車(chē)運(yùn)行

4、起來(lái)。程序也一樣,作為程序開(kāi)發(fā)人員,誰(shuí)都不想讓自己寫(xiě)出來(lái)的代碼有問(wèn)題,但這幾乎是不可能的。好在編寫(xiě)程序的前輩們經(jīng)過(guò)不斷積累與思考,創(chuàng)造了不少好方法處理程序中的異常, Python中,異常最簡(jiǎn)單的化解方式是使用try語(yǔ)句。try語(yǔ)句的語(yǔ)法格式如下:try: #運(yùn)行別的代碼except : #如果在try部份引發(fā)了異常第4頁(yè),共27頁(yè)。try語(yǔ)句的工作原理是,開(kāi)始一個(gè)try語(yǔ)句后,Python就在當(dāng)前程序的上下文中做標(biāo)記,當(dāng)出現(xiàn)異常時(shí)就可以回到做標(biāo)記的地方。如果當(dāng)try后的語(yǔ)句執(zhí)行時(shí)發(fā)生異常,程序就跳回到try并執(zhí)行except子句,異常處理完畢,控制流就通過(guò)整個(gè)try語(yǔ)句(除非在處理異常時(shí)又引發(fā)

5、新的異常)。如果不想在發(fā)生異常時(shí)結(jié)束程序,只需在try語(yǔ)句塊中捕獲異常即可。def exp_exception(x,y): try: a=x/y print(a=, a) return a except Exception: print(程序出現(xiàn)異常,異常信息:被除數(shù)為0)exp_exception(2, 0)第5頁(yè),共27頁(yè)。程序在執(zhí)行過(guò)程中,try語(yǔ)句塊中的語(yǔ)句在執(zhí)行時(shí)發(fā)生異常,程序最后執(zhí)行的是except子句。因?yàn)槿绻Z(yǔ)句正常,應(yīng)該輸出“a=”的形式,但實(shí)際輸出的是except子句中的打印語(yǔ)句的內(nèi)容。在程序執(zhí)行過(guò)程中,如果沒(méi)有將異?;?,異常就會(huì)被“傳播”到調(diào)用的函數(shù)中。如果在調(diào)用的函數(shù)

6、中依然沒(méi)有化解異常,異常就會(huì)繼續(xù)“傳播”,直到程序的最頂層。在實(shí)際應(yīng)用中,經(jīng)常會(huì)遇到需要處理多個(gè)異常的情況,對(duì)于多個(gè)異常該怎么化解呢?Python支持在一個(gè)try/except語(yǔ)句中處理多個(gè)異常,語(yǔ)法格式如下:try: #運(yùn)行別的代碼except : #如果在try部分引發(fā)了name1異常except ,: #如果引發(fā)了name2異常,獲得附加數(shù)據(jù)第6頁(yè),共27頁(yè)。try語(yǔ)句按照如下方式工作:首先執(zhí)行try子句(在關(guān)鍵字try和關(guān)鍵字except之間的語(yǔ)句);如果try子句執(zhí)行沒(méi)有發(fā)生異常,忽略except子句,try子句執(zhí)行后結(jié)束;如果在執(zhí)行try子句的過(guò)程中發(fā)生異常,try子句余下的部分就

7、會(huì)被忽略;如果異常的類(lèi)型和except之后的名稱(chēng)相符,對(duì)應(yīng)的except子句就會(huì)被執(zhí)行,最后執(zhí)行try語(yǔ)句之后的代碼。如果拋出的異常沒(méi)有與任何except匹配,那這個(gè)異常就會(huì)傳遞到上層的try語(yǔ)句中。一個(gè)try語(yǔ)句可能包含多個(gè)except子句,分別處理不同的異常,但最多只有一個(gè)分支會(huì)被執(zhí)行。處理程序只針對(duì)對(duì)應(yīng)try子句中的異常進(jìn)行處理,而不會(huì)處理其他異常語(yǔ)句中的異常。第7頁(yè),共27頁(yè)。9.3 拋出異常Python使用raise語(yǔ)句拋出一個(gè)指定的異常。我們可以使用一個(gè)類(lèi)(應(yīng)該是Exception的子類(lèi))或者實(shí)例參數(shù)調(diào)用raise語(yǔ)句來(lái)引發(fā)異常。使用類(lèi)時(shí),程序會(huì)自動(dòng)創(chuàng)建實(shí)例。如果你只想知道這是否拋

8、出了一個(gè)異常,并不想去處理它,那使用一個(gè)簡(jiǎn)單的raise語(yǔ)句就可以再次把它拋出。如下示例: try: raise NameError(This is NameError)except NameError: print(An exception happened!) #后面不加raiseAn exception happened! #若不加raise,輸出對(duì)應(yīng)字符就結(jié)束第8頁(yè),共27頁(yè)。 try: raise NameError(This is NameError)except NameError: print(An exception happened!) raise #最后加一個(gè)raiseA

9、n exception happened!Traceback(most recent call last): File , line 2, in NameError: This is NameError在實(shí)際應(yīng)用過(guò)程中,可以借助raise語(yǔ)句得到更詳盡的異常信息。第9頁(yè),共27頁(yè)。面碰到的如NameError、SyntaxError、TypeError、ValueError這些異常類(lèi)稱(chēng)為內(nèi)建異常類(lèi)。在Python中,內(nèi)建的異常類(lèi)有很多,可以使用dir函數(shù)列出異常類(lèi)的內(nèi)容(有興趣可以嘗試看看),并且都可以用在raise語(yǔ)句中,用法如raise NameError這般使用。下表描述了一些重要的內(nèi)建

10、異常類(lèi)。異常名稱(chēng)描述Exception常規(guī)錯(cuò)誤的基類(lèi)AttributeError對(duì)象沒(méi)有這個(gè)屬性IOError輸入/輸出操作失敗IndexError序列中沒(méi)有此索引(index)KeyError映射中沒(méi)有這個(gè)鍵NameError未聲明/初始化對(duì)象 (沒(méi)有屬性)SyntaxErrorPython 語(yǔ)法錯(cuò)誤SystemError一般的解釋器系統(tǒng)錯(cuò)誤ValueError傳入無(wú)效的參數(shù)第10頁(yè),共27頁(yè)。9.4 一個(gè)塊捕捉多個(gè)異常上一節(jié)我們講述的是一個(gè)try語(yǔ)句對(duì)應(yīng)多個(gè)except子句,假若需要一個(gè)try對(duì)應(yīng)一個(gè)except子句,同時(shí)捕捉到一個(gè)以上的異常。看如下示例:def model_excepti

11、on(x,y): try: b=name a=x/y except(ZeroDivisionError, NameError, TypeError): print(one of ZeroDivisionError or NameError or TypeError happened)model_exception(2,0)如果需要一個(gè)塊捕捉多個(gè)類(lèi)型異常,可以將他們作為元組列出。第11頁(yè),共27頁(yè)。程序輸出結(jié)果如下:one of ZeroDivisionError or NameError or TypeError happened由輸出結(jié)果可以看到,在一個(gè)try對(duì)應(yīng)一個(gè)except子句時(shí),若將

12、多個(gè)異常放置于一個(gè)元組中,能做到捕獲一個(gè)以上的異常。使用這種方式時(shí),只要遇到的異常類(lèi)型是元組中的任意一個(gè),都會(huì)進(jìn)入異常流程。這么做有什么好處呢?假如希望多個(gè)except子句輸出同樣的信息,就沒(méi)有必要使一個(gè)try語(yǔ)句對(duì)應(yīng)多個(gè)except語(yǔ)句,將多個(gè)except的異常類(lèi)放到一個(gè)except的元組中即可。第12頁(yè),共27頁(yè)。9.5 異常對(duì)象捕捉如果希望在except子句中訪問(wèn)異常對(duì)象本身,也就是看到一個(gè)異常對(duì)象真正的異常信息,而不是打印出自己定義的異常信息,可以使用 as e的形式,稱(chēng)為捕捉對(duì)象。示例如下(model_exception_1.py):def model_exception(x,y):

13、 try: b=name a=x/y except(ZeroDivisionError, NameError, TypeError) as e: print(e)model_exception(2,0)第13頁(yè),共27頁(yè)。看如下示例(model_exception_2.py):def model_exception(x,y): try: a=x/yb=name except(ZeroDivisionError, NameError, TypeError) as e: print(e)model_exception(2,) 在該示例中,調(diào)用函數(shù)時(shí)有一個(gè)實(shí)參傳入的是空值。輸出結(jié)果如下:unsupp

14、orted operand type(s) for /: int and str 第14頁(yè),共27頁(yè)。在實(shí)際編碼過(guò)程中,即使程序能處理好幾種類(lèi)型的異常,但有一些異常還是會(huì)從我們手掌中溜走。上面示例中的異常就逃過(guò)了try/except語(yǔ)句的檢查,對(duì)于這種情況根本無(wú)法預(yù)測(cè)會(huì)發(fā)生什么,也無(wú)法提前做任何準(zhǔn)備。在這種情況下,與其使用不是捕捉異常的try/except語(yǔ)句隱藏異常,不如讓程序立即崩潰。對(duì)于這樣的異常,該用什么方式來(lái)化解?示例如下(model_exception_3.py):def model_exception(x,y): try: b=name a=x/y except: print(E

15、rror happened)model_exception(2,)第15頁(yè),共27頁(yè)??梢栽趀xcept子句中忽略所有異常類(lèi),從而讓程序輸出自己定義的異常信息。這里只是給出了一種可參考的解決方式。從實(shí)用性方面來(lái)講,不建議這么做,因?yàn)檫@樣捕捉異常非常危險(xiǎn),會(huì)隱藏所有沒(méi)有預(yù)先想到的錯(cuò)誤。建議在實(shí)際應(yīng)用中,使用拋出異常的方式處理,或者對(duì)異常對(duì)象e進(jìn)行一些檢查。第16頁(yè),共27頁(yè)。9.6 豐富的else子句異常為我們提供了try.except.else的語(yǔ)句來(lái)實(shí)現(xiàn)該功能,其語(yǔ)法如下:try: #運(yùn)行別的代碼except : #如果在try部份引發(fā)了異常1except ,: #如果引發(fā)了異常2,獲得附加

16、的數(shù)據(jù)else: #如果沒(méi)有異常發(fā)生第17頁(yè),共27頁(yè)。如果在try子句執(zhí)行時(shí)沒(méi)有發(fā)生異常,python將執(zhí)行else語(yǔ)句后的語(yǔ)句(如果有else的話)。使用else子句比把所有的語(yǔ)句都放在 try 子句里面要好,這樣可以避免一些意想不到的而except又沒(méi)有捕獲的異常。如下示例(model_exception_4.py):def model_exception(x, y): try: a=x/y except: print(發(fā)生異常,走的是except邏輯。) else: print(沒(méi)有發(fā)生異常,走的是else邏輯。)model_exception(2, 1) #model_excepti

17、on函數(shù)調(diào)用當(dāng)程序沒(méi)有發(fā)生異常時(shí),通過(guò)添加一個(gè)else子句來(lái)做一些事情是很有用的,它可以幫助我們更好的判斷程序的執(zhí)行情況。第18頁(yè),共27頁(yè)。9.7 自定義異常盡管內(nèi)建異常類(lèi)包括了大部分異常,也可以滿(mǎn)足很多要求,但有一些情況還是需要?jiǎng)?chuàng)建自己的異常類(lèi)才能處理。比如,若需要精確知道問(wèn)題的根源,就需要使用自定義異常來(lái)精確定位問(wèn)題??梢酝ㄟ^(guò)創(chuàng)建一個(gè)新exception類(lèi)擁有自己的異常。異常應(yīng)該繼承自Exception類(lèi),可以直接繼承,也可以間接繼承。錯(cuò)誤就是類(lèi),捕獲一個(gè)錯(cuò)誤就是捕獲該類(lèi)的一個(gè)實(shí)例,因此錯(cuò)誤并不是憑空產(chǎn)生的,而是由一些不合理的部分導(dǎo)致的。Python的內(nèi)置函數(shù)會(huì)拋出很多類(lèi)型的錯(cuò)誤,自己編

18、寫(xiě)的函數(shù)也可以拋出錯(cuò)誤。如果要拋出錯(cuò)誤,那么可以根據(jù)需要定義一個(gè)錯(cuò)誤的類(lèi),選擇好繼承關(guān)系,然后用raise語(yǔ)句拋出一個(gè)錯(cuò)誤的實(shí)例。代碼示例(my_error.py)第19頁(yè),共27頁(yè)。9.8 try-finally語(yǔ)句Python中的finally子句需要和try子句一起使用,組成try/finally的語(yǔ)句形式。try/finally語(yǔ)句無(wú)論發(fā)生異常與否都將執(zhí)行finally后的代碼。示例如下(use_finally.py):def use_finally(x,y): try: a=x/y finally: print(No matter what happened,I will show

19、in front of you)use_finally(2,0)第20頁(yè),共27頁(yè)。其實(shí)在Python中,不管try子句中是否發(fā)生異常,finally子句都會(huì)執(zhí)行。這里有一個(gè)疑問(wèn),雖然執(zhí)行了finally子句,但是最后仍然有異常拋出,是否可以使用except截獲異常呢?可以使用except來(lái)截獲異常。try、except、else和finally可以組合使用,但放置的順序規(guī)則是:else在except之后,finally在except和else之后。第21頁(yè),共27頁(yè)。9.9 函數(shù)中的異常如果異常在函數(shù)內(nèi)引發(fā)而不被處理,就會(huì)傳播至函數(shù)調(diào)用的地方。如果異常在函數(shù)調(diào)用的地方也沒(méi)有被處理,就會(huì)繼續(xù)傳

20、播,一直到達(dá)主程序。如果在主程序中也沒(méi)有做異常處理,異常就會(huì)被Python解釋器捕獲,輸出一個(gè)錯(cuò)誤信息,然后退出程序。示例如下(division_fun.py):def division_fun(x, y): return x / int(y)def exp_fun(x, y): return division_fun(x, y) * 10第22頁(yè),共27頁(yè)。def main(x,y): exp_fun(x, y)main(2,0)在Python中,異常信息是以堆棧的形式被拋出的,因而是從下往上查看的。所謂堆棧,就是最先被發(fā)現(xiàn)的異常信息最后被輸出(就像子彈入彈夾和出彈夾一樣),也被稱(chēng)為先進(jìn)后出(First In Last Out,F(xiàn)ILO)。第23頁(yè),共27頁(yè)。9.10 活學(xué)活用正常數(shù)異常數(shù)對(duì)給定的數(shù)組,數(shù)組中的前后兩個(gè)數(shù)相除,若被除數(shù)為0,則認(rèn)為是異常數(shù),需要通過(guò)自定義異常打印出異常信息,并將該異常數(shù)加入異常數(shù)組中;若被除數(shù)

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論