摘要:與異常相關的編程藝術異常代替返回狀態碼我們經常需要編寫一些工具類的函數,往往在這些函數的處理流程中,會產生很多的狀態而這些狀態也是調用者需要得到的信息。
編程中經常會需要使用到異常處理的情況,在閱讀了一些資料后,整理了關于異常處理的一些小技巧記錄如下。
如何自定義異常 定義異常類在實際編程中,有時會發現Python提供的內建異常的不夠用,我們需要在特殊業務場景下的異常。這時就需要我們來定義自己的異常。按照Python約定俗成的習慣,用戶定義的異常一般都是繼承于Exception類,由它開始拓展。后面我們可以看到這樣做在捕獲異常的時候會帶來很大的便利。
>>> class MyError(Exception): pass >>> raise MyError(u"something error") Traceback (most recent call last): File "API異常相關的技巧", line 1, in __main__.MyError: something error
定義API異常的技巧API的異常分為定義異常與調用API時如何捕獲異常兩個部分,這二者相輔相成。
在自己編寫API的時候,應該定義Root Exception——API中的根異常,其它異常都繼承于它。這樣的做法有兩個好處:
API代碼層次更清晰
API與調用程序代碼隔離
假設存在如下場景:需要做一個鏈接數據庫服務的模塊。提供一個connect函數用于鏈接。那么,在鏈接的過程中,就會發生以下幾種情況:
socket連接超時
socket拒絕連接
針對以上的情況,我們在模塊中定義幾個異常:
# database.py class Error(Exception): """Root exception for all exceptions raised by this module.""" class SocketTimeError(Error): pass class SocketRefuseError(Error): pass def connect(): pass調用API時異常捕獲的技巧
這樣在調用API的時候就可以這樣使用:
try: connect() except SocketTimeError as err: log.error(err) except SocketRefuseError as err: log.error(err) except Error as err: log.error("API Unexpected error:%s" % err) except Exception: log.error("API bug cause exception.")
這樣精確定義多個異常,使得代碼層次清晰,增強了可讀性。值得注意的是:在代碼的最后還捕獲了Error以及Exception兩個異常,這兩個操作分別對應于可拓展性與健壯性的目的。
我們知道,在實際鏈接數據庫時,還可能會出現用戶沒有登陸權限等問題。所以,我們需要在下一個版本中加入PermissionDeny這個異常。但是,舊的調用代碼已經寫好了,如果忘記修改的話,這個異常可能就會無法被處理,進而使得調用的程序奔潰。處于這樣的考慮,我們在調用API的時候,就應該再捕獲API的Root Exception,即使之后新加入了其它的異常,在這一個except中也能被捕獲而不影響調用程序。使得API模塊的可拓展性得到了提高。
在調用API的時候,難免可能出現API內部存在bug的情況。這個時候如果捕獲了Exception的話,就算API內部因為bug發生了異常,也不會影響到調用程序的正常運行。
從這兩點中可以看出,要達到這種效果,其實都要依賴于常規異常繼承于Exception類這個規矩。這樣的架構劃分所帶來的好處是顯而易見的。
與異常相關的編程藝術 異常代替返回狀態碼我們經常需要編寫一些工具類的函數,往往在這些函數的處理流程中,會產生很多的狀態;而這些狀態也是調用者需要得到的信息。很多時候,會用一些具有意義的返回值來表示函數處理的狀態。
比如:
def write(content): if isinstance(content, basestring): f_handler = open("file.txt", "w") try: f_handler.write(context) except Exception: return -2 # write file fail else: return 0 # write file succcess finally: f_hanlder.close() else: return -1 # arg type error
調用代碼:
result = write() if result == -1: log.error(u"type error") elif result = -2: log.error(u"write error") else: log.info("ok")
這種狀態碼的方式使用起來特別的不方便,調用者還需要去理解每個狀態碼的意義,帶來其它的學習成本;而且用if-else結構也不易于后期的程序拓展。所以,我們可以使用觸發異常來代替返回狀態碼,每個異常名其實就包含了狀態的意義在內(命名的藝術),使用起來也更好理解。
使用異常的方式:
class Error(Exception): pass class OpenFileError(Error): pass class WriteContentError(Error): pass def write(content): if isinstance(content, basestring): f_handler = open("file.txt", "w") try: f_handler.write(context) except Exception: raise WriteContentError finally: f_hanlder.close() else: raise OpenFileError
調用代碼:
try: write() except OpenFileError as e: log.error(e) except WriteContentError as e: log.error(e) except Error: log.error("API Error") except Exception log.error("API Bug") else: log.info("ok")
結合上面一點提到的使用API時的異常捕獲,使得調用代碼變得更佳靈活。
異常處理與流程控制錯誤處理很重要,但如果它搞亂了代碼邏輯,就是錯誤的做法
將異常處理與正常流程控制混為一談時,代碼是十分丑陋的。我們應該將二者分離,最好的做法就是將異常代碼塊抽離到另外的函數中。
try: action_a() action_b() action_c() except ActionException as e: log.error(e) else: action_d()
將異常處理分離:
def action_executor(): action_a() action_b() action_c() def action(): try: action_executor() except ActionException as e: log.error(e) action() action_d()參考資料
《clean code》
《Python3 OOP》
《effective python》
python官方手冊
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/38080.html
摘要:前言最近之父龜爺終于在官方郵件組落實了的終焉之日。于之后的年月日發布,計劃作為的最后一個版本。統一使用作為縮進,如果和同時存在,就會觸發異常兼容技巧統一使用作為縮進。兼容技巧統一使用內置函數。統一輸出函數中的即是關鍵字又是內置函數。 前言 最近 Python 之父 Guido van Rossum(龜爺)終于在 Python 官方郵件組落實了 Python 2.7 的終焉之日(EOL)...
摘要:本文的分享主要圍繞以下幾個方面能做什么常見應用場景介紹如何學習語法基礎實戰面向對象編程實戰練熟基礎小游戲項目的實現與實戰一能做什么一種編程語言往往可以應用于多方面,有些方面比較常用,有些方面極為常用。比如表示是一個空列表。 摘要:Python語言的教程雖然隨處可見,但是忙于日常業務/學習的你或許:一直想要找個時間學一點,但是又不知道該從何下手?本文將從Python能做什么,如何學習Py...
摘要:對于異常機制的合理運用是直接關系到碼農飯碗的事情所以,本文將具體介紹一下和的異常處理機制,闡明二者在異常處理機制上的異同。下面將具體介紹二者的異常處理機制。 概述 showImg(https://segmentfault.com/img/remote/1460000006760426); 異常處理,是編程語言或計算機硬件里的一種機制,用于處理軟件或信息系統中出現的異常狀況(即超出程序正...
摘要:盡量使用內置的異常處理語句來替換語句,比如語句,方法。以上是最簡單的重新拋出異常的做法,也是推薦的做法。除了包含所有的外還包含了,和三個異常。避免在語句塊中干一些沒意義的事情,捕獲異常也是需要成本的。 異常處理在任何一門編程語言里都是值得關注的一個話題,良好的異常處理可以讓你的程序更加健壯,清晰的錯誤信息更能幫助你快速修復問題。在Python中,和不部分高級語言一樣,使用了try/ex...
摘要:引上下文管理器太極生兩儀,兩儀為陰陽。而最常用的則是,即上下文管理器使用上下文管理器用之后的文件讀寫會變成我們看到用了之后,代碼沒有了創建,也沒有了釋放。實現上下文管理器我們先感性地對進行猜測。現實一個上下文管理器就是這么簡單。 Python有什么好學的這句話可不是反問句,而是問句哦。 主要是煎魚覺得太多的人覺得Python的語法較為簡單,寫出來的代碼只要符合邏輯,不需要太多的學習即可...
閱讀 2566·2021-09-02 15:40
閱讀 1572·2019-08-30 15:54
閱讀 1083·2019-08-30 12:48
閱讀 3403·2019-08-29 17:23
閱讀 1051·2019-08-28 18:04
閱讀 3669·2019-08-26 13:54
閱讀 610·2019-08-26 11:40
閱讀 2399·2019-08-26 10:15