第13條:合理利用try/expect/else/finally結構中的每個代碼塊


核心知識點:

(1)無論try塊是否發生異常,都可以使用try/finally復合語句中地finally塊來執行清理工作。

(2)順利運行try塊后,若想使某些操作能在finally塊地清理代碼之前執行,則可將這些操作寫入到else塊中

 

Python程序的異常處理可能要考慮四種不同的時機。這些時機可以用try、expect、else和finally塊來表述。

復合語句中的每個塊都有特定的用途,它們可以構成很多種有用的組合方式。

 

1.finally塊

如果既要將異常向上傳播,又要在異常發生時執行清理工作,那就可以使用try/finally結構。

這種結構有一項常見的用途,就是確保程序能夠可靠地關閉文件句柄。

>>> handle = open('/tmp/my_file.txt')
>>> try:
...     data = handle.read()
... finally:
...     handle.close()

上面這段代碼中,read方法所拋出的異常會向上傳播給調用方,而finally塊中的handle.close()方法則一定能夠執行。

open方法必須放在try塊外面,應為如果打開文件時發生異常,那么程序應該跳過finally塊。

 

2.else塊

try/expect/else結構可以清晰地描述出那些異常會由自己的代碼來處理,那些異常會傳播到上一級。

如果try'塊沒有發生異常,那么就執行else塊。有了這種else塊,我們可以盡量縮減try塊內的代碼量,使其更加易懂。

例如,要從字符串中加載JSON字典數據,然后返回字典里某個鍵所對應地值。

>>> def load_json_key(data,key):
...     try:
...         result_dict = json.loads(data)
...     except ValueError as e:
...         raise KeyError from e
...     else:
                return result_dict[key]

如果數據不是有效地JSON格式,那么用json.loads解碼時,會產生ValueError。這個異常會由except塊來捕獲並處理。

如果能夠解碼,那么else塊里地查找語句就會執行,它會根據鍵來查出相關地值。查詢時若有異常,則該異常會向上傳播,因為查詢語句並不在剛才那個try塊地范圍內。

這種else子句,會把try/except后面地內容和except塊本身區分開來,使異常地傳播行為變得更加清晰。

 

 

3.混合使用

如果要在復合語句中把上面幾種機制都用到,那就編寫完整地try/except/else/fianally結構。

例如,要從文件中讀取某項事務地描述信息,處理該事務,然后就地更新該文件。

為了實現本功能,我們可以用try塊來讀取文件並處理其內容,用except塊來應對try中可能發生地相關問題,

用else塊實時地更新文件並把更新中可能出現地問題回報給上級代碼,然后用finally塊來清理文件句柄。

UNDEFINED = object()

def divide_json(path):
    handle = open(path,'r+')
    try:
        data = handle.read()
        op = json.loada(data)
        value = (
            op['numerator'] /
            op['denominator'])
    except ZeroDivisionError as e:
        return UNDEFINED
    else:
        op['result'] = value
        result = json.dumps(op)
        handle.seek(0)
        handle.write(result)
        return value
    finally:
        handle.close()

這種寫法很有用,因為這四塊代碼相互配合非常到位。

 

文章摘抄於Brett Slatkin的《編寫高質量Python代碼的59個有效方法》,僅作為個人學習使用,如有侵權請告知,將及時刪除,如果覺得有益,請購買原版書籍,知識需要傳遞和支持,謝謝。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM