""" 什麼是異常: 一、異常指出了咱們的程序有錯誤 二、有些異常也會在一些合法的狀況下發生,好比用戶名密碼錯誤,銀行卡號不存在 三、內置異常的名字都是以Error結尾:ZeroDivisionError,IndexError,SyntaxError 四、全部異常類都是繼承於Exception,(擴展BaseException) 五、當一個異常發生的時候,會當即中止程序的執行,除非正確的處理這個異常 六、異常是一個對象,而且能夠繼承(經過繼承Exception類來實現本身的異常) """ # print "hello" #拋出異常信息:SyntaxError: Missing parentheses in call to 'print'. Did you mean print("hello")? #產生的SyntaxError異常,這就是異常,語法錯誤的異常 #x = 5 / 0 #print(x) #拋出ZeroDivisionError異常,信息:ZeroDivisionError: division by zero,說是不能被除 # lst = [1,2,3] # print(lst[3]) #拋出異常:IndexError: list index out of range 說是索引錯誤 #經過內置的TypeError和ValueError類來構造異常對象,下面的例子擴展了內置的list,並重寫了該內之類的append方法 class MyList(list): #繼承內置的list類 def append(self, integer): if not isinstance(integer, int): #若是不是整數則拋出異常 raise TypeError("Not an integer") if integer % 2: raise ValueError("Can not be divisible") #不能整除時則拋出異常 super().append(integer) #調用父類的append方法 # mylist = MyList() # #mylist.append(12.45) #引起TypeError異常 # #mylist.append(87) #引起ValueError異常 # mylist.append(64) #無異常 #發生異常時,程序是怎樣的? def test_return(): print("hello") #這條是會被執行的 raise Exception("My God, something went wrong") #這裏引起異常後,後面的代碼永遠不會執行,包括return語句 print("How are you?") return "I'm very good" #test_return() #經過另一個函數來調用test_return函數,看看效果 def call_test_return(): print("start call...") test_return() #在這裏調用test_return函數 print("an exception was raised....") print("so...") #call_test_return() """ 在call_test_return函數中調用test_return函數,在test_return函數中有異常的發生 可是對於call_test_return函數是沒有異常語句的。可爲何連call_test_return函數都中止執行了呢? 緣由是: 異常拋出會中止在call_test_return函數調用棧內全部代碼的執行 """ #即然有異常,就要處理它,如何處理? # try: # test_return() # except: #在這裏捕捉到了異常,所以輸出下面的print語句 # print("test_return Function An exception occurs") #提示有異常發生 # print("end...") """ 捕捉了異常,而且在發生異常時應該作什麼,所以,程序沒有被終止掉 對於在test_return函數,在拋出異常的語句以後的代碼是沒有被執行的 一、try語句能夠包含任何可能會發生異常的代碼 二、except語句將捕獲任何類型的異常,而不是捕獲有針對性的異常,它是捕獲全部。 三、那麼如何捕獲指定的異常類型?看下面代碼 """ #捕捉指定的異常類型 def func_a(number): try: return 100 / number except ZeroDivisionError: print("Can not be 0") # print(func_a(0)) #拋出ZeroDivisionError類型的異常 # print(func_a("abcdef")) #拋出TypeError類型的異常,但目前爲止的代碼,沒有寫捕獲TypeError類型的異常,所以這個異常沒法被捕捉 #也就是說,TypeError異常,不包含在要處理的異常類型中 #那麼如何才能同時捕捉多種類型的異常?改進代碼,以下 def func_b(number): try: return 100 / number except (ZeroDivisionError, TypeError): print("Unknown value...") # print(func_b(0)) # print(func_b("abcdef")) #很是完美,貌似這兩種異常類型都捕捉到了 #可是,這裏有一個弊端,就是,我想捕獲不一樣類型的異常而且對它們作出不一樣的操做,目前的代碼是沒法實現的, #那麼,爲了實現這個想法,繼續改進代碼,以下 def func_c(number): try: return 100 / number except ZeroDivisionError: print("Unknown value...") #捕獲到ZeroDivisionError異常,就執行此操做 except TypeError: print("Value Type Error...") #捕獲到TypeError異常,就執行這個操做 # func_c(0) # func_c("abc") # print(func_c(89)) #所以,很是完美! #思考一個問題,若是捕獲任何類型的異常再最前面會是什麼狀況?看以下代碼 def func_d(number): try: return 100 / number except Exception: #捕獲任何異常類型 print("Exception....") except ZeroDivisionError: print("Unknown value...") except TypeError: print("Value Type Error...") # func_d(0) # func_d("abc") #效果是,雖然明確知道會發生哪一種類型的異常並有針對性的捕獲,可是捕獲任何類型異常在最前面,致使有針對性的捕獲根本就沒有捕獲 #爲何會這樣?由於ZeroDivisionError,TypeError這些內置的異常類型都是從Exception類繼承而來的,也就是說,已經捕獲了,就不必再去有針對性的捕獲。 #OK,那麼若是將他們的順序反過來(也就是except Exception在最後面),又會是啥狀況?看下面的代碼(下面的代碼去掉了捕獲TypeError類型) def func_e(number): try: return 100 / number except ZeroDivisionError: print("Unknown value...") except Exception: #捕獲任何異常類型 print("all Exception....") # func_e(0) #這裏引起的是ZeroDivisionError類型的異常 # func_e("abc") #這裏本來是引起TypeError類型的異常,但去掉後所以沒法捕捉,因此由except Exception語句來負責捕獲剩下的全部異常 #經過效果,很是完美,而該在怎樣的應用場景去使用它已經沒必要多說,很顯然知道怎麼去應用它了 """ 有沒有注意到,在上面的例子中,捕獲異常以後所作的操做是打印一句話, 可是實際的操做不僅是打印一句話,也能夠是作別的操做,好比作運算,或者繼續循環,或者斷開鏈接等等操做 有一種狀況是,我不想僅僅只是作操做,我還想知道它所引起的異常的具體信息。那麼如何查看?看下面的代碼 """ def func_f(number): try: return 100 / number except ZeroDivisionError as err: print("[Error]:%s [args]:%s" % (err, err.args)) # func_f(0) #這裏是經過as關鍵字來捕獲到異常做爲變量來訪問,err.args則是獲取傳給函數的參數 #關鍵字as,在異常中使用,是在python3版本中,而對於python2,則使用的是一個逗號 """ 以前說了,把可能發生異常的代碼丟進try中,那麼若是被丟進try的代碼沒有發生異常呢? 若是沒有異常,不只要執行try中的代碼,而且同時我還須要執行別的操做, 若是有異常的發生,那麼就只捕獲異常,並執行對應的動做,無需執行別的額外操做。 那麼請看下面改進後的代碼 """ def func_g(number): try: ret = 100 / number print(ret) except ZeroDivisionError as err: print("[Error]:%s [args]:%s" % (err, err.args)) else: print("calculation done...") # func_g(5) #傳入5到函數中進行計算,沒有異常,沒有異常而且也要執行else後面的語句,所以達到了目的 # func_g(0) #傳入0,則引起異常,那麼僅僅只是執行了except中的捕獲操做,else後面的語句沒有被執行 """ 上面的代碼彷佛很是完美,我又有一個需求,就是語句不管是否發生異常都將執行我指定的操做 改進以下 """ def func_h(number): try: ret = 100 / number print(ret) except ZeroDivisionError as err: print("[Error]:%s [args]:%s" % (err, err.args)) else: print("calculation done...") finally: print("code end...") # func_h(0) #傳入0,引起異常,而且,也繼續執行了finally後面語句,可是else則沒有執行,很是完美,達到個人目的 # func_h(8) #傳入的是8,沒有異常則無需捕獲,那麼else是在沒有異常的狀況下才執行,那麼他執行了。這很是正確,finally後面的語句也執行了 #經過看到的效果,finally確實是無論有沒有異常的發生,都確實是會執行