閱讀目錄:
1、異常 Exception
2、産生異常
3、異常的捕獲
4、異常類及繼承層次
5、BaseException及子類
6、Exception 及子類
7、異常的捕獲
8、as子句
9、finally 子句
10、異常嵌套
11、else語句
12、異常的捕獲時機
13、總結
1、異常 Exception
錯誤 和 異常的差別:
錯誤:Error
邏輯錯誤:算法錯誤,加法寫成了減法
筆誤:變量名寫錯了,文法錯誤
函數或類使用錯誤,其實這也屬于邏輯錯誤
總之錯誤是可以避免的
異常:Exception
本意就是意外情況
這有個前提,沒有出現上面說的錯誤,也就是說程式寫的沒問題,但是在某些情況下,會出現一些意外,導緻程式無法正常的執行下去
例如open函數,操作一個檔案,檔案不存在,或建立一個檔案已經存在,或通路一個網絡檔案突然斷網了,這就是一場,是個意外的情況。
異常是不可能避免的
錯誤和異常:
在進階程式設計語言中一般都有錯誤和異常的概念,異常是可以捕獲,并被處理的,但是錯誤是不能被捕獲的。
舉例:
異常:
錯誤:
總結:
一個健壯的程式
盡可能的避免錯誤
盡可能的捕獲,處理各種異常。
Python的特點是,将Error放到異常類中。
2、産生異常:
産生:
raise 語句顯式的抛出異常(手動抛出)
Python解釋器自己檢測到異常并引發它
舉例:
解釋器自動抛出:
手動抛出:
程式會在異常抛出的地方中斷執行,如果不捕獲,就會提前結束程式(其實是終止目前線程的執行)
raise:
raise 後面什麼都沒有,表示抛出最近一個被激活的異常,如果沒有被激活的異常,則抛類型異常,這種但是很少使用。
raise 後要求應該是BaseException類的子類或執行個體,如果是類,将被無參執行個體化
raise IndexError() :無參構造 ----BaseException的派生類
raise IndexError :無參構造 ----BaseException的派生類
raise IndexError('index error') :有參構造 ----BaseException的派生類
3、異常的捕獲:
文法:
1 try:2待捕獲異常的代碼塊,隻要出現一條異常,就會終止,後面的執行,跳到except3 except[異常類型]:4 異常的處理代碼塊
舉例:
1:
2:
3:
4、異常類及繼承層次:
擷取BaseException的子類:
1 def foo(cls, count=0):2 for i in cls.__subclasses__():3 if count ==0:4 print(count * '\t' + '+--' +str(i))5 else:6 print((count - 1) * '\t'+ '|' + '\t' + '+--' +str(i))7 if i.__subclasses__() :8 count += 1
9 foo(i, count)10 else:11 continue
12
13
14 foo(BaseException)
View Code
結果:
1 +--
2 | +--
3 | +--
4 | +--
5 | +--
6 | +--
7 | +--
8 | +--
9 | +--
10 | +--
11 | +--
12 | +--
13 | +--
14 | +--
15 | +--
16 | +--
17 | +--
18 | +--
19 | +--
20 | +--
21 | +--
22 | +--
23 | +--
24 | +--
25 | +--
26 | +--
27 | +--
28 | +--
29 | +--
30 | +--
31 | +--
32 | +--
33 | +--
34 | +--
35 | +--
36 | +--
37 | +--
38 | +--
39 | +--
40 | +--
41 | +--
42 | +--
43 | +--
44 | +--
45 | +--
46 | +--
47 | +--
48 | +--
49 | +--
50 | +--
51 | +--
52 | +--
53 | +--
54 | +--
55 | +--
56 | +--
57 | +--
58 | +--
59 | +--
60 | +--
61 | +--
62 | +--
63 | +--
64 | +--
65 | +--
66 | +--
67 | +--
68 | +--
69 +--
70 +--
71 +--
View Code
5、BaseException及子類
BaseException是所有内建異常類的基類
SystemExit
sys.exit() 函數引發的異常,異常不捕獲處理,就直接交給Python解釋器,解釋器退出。
如果except語句捕獲了該異常,則繼續向後進行,如果沒有捕獲,解釋器直接退出目前執行的程式
Keyboardinterrupt:
對應的捕獲使用者中斷行為 Ctrl+ c
測試:
本地建立一個.py 檔案,輸入如下代碼:
1 try:2 importtime3 whileTrue:4 time.sleep(2)5 print('_________')6 exceptKeyboardInterrupt:7 print('ctrl + c')8 print('out')
在cmd中執行該檔案,可以通過ctrl + c 結束中斷。
6、Exception 及子類:
Exception是所有内建的,非系統退出的異常的基類,自定義的異常應該繼承他
SyntaxError 文法錯誤:是無法捕獲的,直接識别出來。但在python中是歸并到異常類的Exception下的子類
ArithmeticError所有算術引發的異常,其子類有除零異常等。
LookupError:使用映射的鍵或序列的索引無效時引發的異常的基類:IndexError,KerError
自定義異常:
從Exception繼承的類
7、異常的捕獲:
except可以捕獲多個異常:
總結:
捕獲規則
捕獲是從上到下依次比較,如果比對,則執行比對的except語句塊
如果被一個except語句捕獲,其他except語句就不會再次捕獲了
如果沒有任何一個except語句捕獲到這個異常,則該異常就向外抛出
捕獲原則:
從小到大,從具體到寬泛
8、as子句:
被抛出的異常,應該是異常的執行個體 ,如何獲得這個對象呢,使用as語句。
上面是因為,調用無參構造器,事實上 是有參,但沒有預設值是以在調用的時候,産生異常。
關于 raise 的問題:
一般檔案open的都是關于OsError的異常,一般 as e 這個e執行個體,送到日志中去。
9、finally 子句:
finally:最終,即最後一定要執行的,try-----finally語句快中,不管是否發生了異常,都要執行finally的部分。
測試:return必須寫在try語句結構中,如果在最上面,直接傳回,函數調用結束了。
一般不這樣做,return不會寫到 except,finally中,很少這樣操作。
如果沒有except,就是任何異常都不管,向外抛。
測試嵌套,以及怎麼處理檔案句柄清理:
raise用法:
測試1:
測試2:
壓制異常:使用return
測試1:
測試2:
10、異常嵌套
11、else語句:
12、異常的捕獲時機
1、立即捕獲:
需要立即傳回一個明确的結果。
也就是說,可能産生異常,如果出現異常,立即處理。
1 defparse_int(s):2 try:3 returnint(s)4 except:5 return06 print(parse_int('s'))
2、邊界捕獲:
封裝産生了邊界:
例如:寫了一個子產品,使用者調用這個子產品的時候,捕獲異常,子產品内部不需要捕獲,處理異常,一番内部處理了,外部調用者就無法感覺了。
例如:open函數,出現的異常交給調用者處理,檔案存在了,就用在建立了,看是否修改還是删除。
例如:自己寫一個雷,使用open函數,但是出現了異常不知道如何處理,就繼續往外層抛,一般來說,最外層也是邊界,必須處理這個異常了,否則線程退出。
也就是一句話:提供功能的,就不要捕獲異常了,往外抛,讓調用者感覺到異常。讓調用者處理。
13、總結:
try:
<> 運作别的代碼
except :
<> 捕獲某種類型的異常
else:
<> 如果沒有發生異常
finally:
<> 退出try 時總會執行
try工作原理:
如果try 中語句執行時發生異常,搜尋except子句,并執行第一個比對該異常的except子句
如果try中語句執行時發生異常,卻沒有比對的except子句,異常将被遞交到外層的try,如果外層不處理這個異常,異常将繼續往外【抛,如果都不能處理,則會傳遞到最外層,如果還是沒有處理,就終止異常所在的線程。
如果try執行時沒有發生異常,将執行else語句
無論try中是否發生異常,finally子句最終 都會執行。