1. 程式人生 > >try…finally與巢狀及自定義異常丟擲

try…finally與巢狀及自定義異常丟擲

try...finally...

try...finally...語句用來表達這樣的情況:在程式中,如果一個段程式碼必須要執行,即無論異常是否產生都要執行,那麼此時就需要使用finally。 比如檔案關閉,釋放鎖,把資料庫連線返還給連線池等。

try:

    f = open("log.txt","r")

    a = 10

    b = 0

    ret = a / b

#捕獲多個型別的異常

except IOError as ex:

    print(ex)

except ZeroDivisionError as ex:

    print(ex)

else:

    print

("沒有異常,真是happy!")

finally:

    print("無論是否異常發生,都會執行!")

import time

try:

    f = open('log.txt')

    try:

        while True:

            content = f.readline()

            if len(content) == 0:

                break

            time.sleep(2)

            print(content)

    except KeyboardInterrupt:

        #如果在讀取檔案的過程中,產生了異常,那麼就會捕獲到

        #比如按下了 ctrl+c

        print("捕獲到了以外終止異常!")

    finally:

        f.close()

        print('關閉檔案')

except:

    print("沒有這個檔案")

test.txt檔案中每一行資料列印,但是我有意在每列印一行之前用time.sleep方法暫停2秒鐘。這樣做的原因是讓程式執行得慢一些。在程式執行的時候,按Ctrl+c中斷(取消)程式。

我們可以觀察到KeyboardInterrupt異常被觸發,程式退出。但是在程式退出之前,finally從句仍然被執行,把檔案關閉。

 try巢狀

import time

try:

    f = open('log.txt')

    try:

        while True:

            content = f.readline()

            if len(content) == 0:

                break

            time.sleep(2)

            print(content)

    finally:

        f.close()

        print('關閉檔案')

except:

    print("沒有這個檔案")

函式巢狀呼叫中:

def myDiv(a, b):

    return a / b

def test2():

    a = 10

    b = 0

    try:

        ret = myDiv(a, b)

    except:

        print("test02已經捕獲到了異常,但是不想處理!")

        #手動上拋異常

        raise

def test3():

    try:

        test2()

    except Exception as ex:

        print(ex)

#myDiv函式丟擲異常

#test02沒有處理,異常自動上拋

#test03接收到異常,並處理

#也就是說,異常是跨函式的

test3()

 總結:

  • 如果try巢狀,那麼如果裡面的try沒有捕獲到這個異常,那麼外面的try會接收到這個異常,然後進行處理,如果外邊的try依然沒有捕獲到,那麼再進行傳遞。
  • 如果一個異常是在一個函式中產生的,例如函式A---->函式B---->函式C,而異常是在函式C中產生的,那麼如果函式C中沒有對這個異常進行處理,那麼這個異常會傳遞到函式B中,如果函式B有異常處理那麼就會按照函式B的處理方式進行執行;如果函式B也沒有異常處理,那麼這個異常會繼續傳遞,以此類推。。。如果所有的函式都沒有處理,那麼此時就會進行異常的預設處理,即通常見到的那樣。
  • 注意觀察上圖中,當呼叫test3函式時,在test1函式內部產生了異常,此異常被傳遞到test3函式中完成了異常處理,而當異常處理完後,並沒有返回到函式test1中進行執行,而是在函式test3中繼續執行。

 自定義異常丟擲

你可以用raise語句來引發一個異常。異常/錯誤物件必須有一個名字,且它們應是Error或Exception類的子類。

下面是一個引發異常的例子:

#自定義異常類

class OutOfRangeException(Exception):

    def __init__(self,errMsg):

        self.msg = errMsg

    def __str__(self):

        return self.msg

class Person(object):

    def __init__(self):

        self.name = None

        self.age = None

    def setAge(self,age):

        if age < 0 or age > 100:

            raise  OutOfRangeException("年齡應該在0-100之間!")

        self.age = age

    def setName(self,name):

        self.name = name

    def __str__(self):

        return "name:{} age:{}".format(self.name,self.age)

if __name__ == "__main__":

    person = Person()

    person.setName("Edward")

    person.setAge(80)

    print(person)

try:

    person.setAge(101)

except OutOfRangeException as ex:

    print(ex)