天天看點

《資料結構與算法:Python語言描述》一2.4Python異常

本節書摘來自華章出版社《資料結構與算法:python語言描述》一書中的第2章,第2.4節,作者 裘宗燕,更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視

現在簡單介紹python異常與類的關系,語言内建的異常類層次結構,以及python語言如何利用面向對象的觀點組織異常處理過程。程式設計中有時需要自己定義異常(類型),如果需要這樣做,就應該選一個系統異常類,從它派生。

異常是python語言中的一套特殊的控制機制,主要用于支援錯誤的檢查和處理,也可以用于實作特殊的控制轉移。如果程式執行中發生異常,無論是解釋器發現的異常情況(例如除零或類型錯誤等),還是通過raise語句引發的異常,正常執行控制流立刻終止,解釋器轉入異常處理模式,查找能處理所發生異常的處理器。如果找不到相應的異常處理器,在互動解釋環境下,系統将在環境中輸出錯誤資訊,結束目前執行并回到系統的互動狀态,等待下一輸入。在直接執行方式下,目前程式直接終止。

程式運作中發生的每個異常都有特定的名字,如valueerror、typeerror、zerodivision-error等,解釋器根據發生的異常去查找處理器。python裡處理異常的結構是try語句。每個try語句可以帶有任意多個except子句,這種子句就是異常處理器,子句頭部用一個表達式描述它捕捉和處理的異常。

實際上,python的異常都是類(class),運作中産生異常就是生成相應類的執行個體對象,異常處理機制完全基于面向對象的概念和性質。全體内部異常類構成了一個樹形結構,所有異常類的基類是baseexception,其最主要的子類是exception,内置異常類都是這個類的直接或間接派生類。如果使用者需要定義異常,就應該從系統異常類中選擇一個合适的異常,從它派生出自己的異常類。例如:

最簡單的情況(很常見)隻是希望定義一種特殊異常,并不需要這種異常有什麼特殊功能(如上即是)。在這種情況下,選一個系統異常類派生自己的異常類,類體不需要定義任何屬性。但為了文法完整,可以在這裡寫一個pass語句。

如果運作中發生異常,查找相應處理器的工作由解釋器完成,這裡的工作方式也基于對象和類的關系。在一個except子句頭部可以列出一個或多個異常名(一般說,是表示異常類的表達式),列出多個異常名時需要采用括号括起的元組形式。列在except子句頭部的異常名表示本異常處理器準備捕捉和處理的異常。

運作中發生的異常與處理器的比對按面向對象的方式處理。假設運作中發生的異常是e,如果一個異常處理器頭部列有異常名e,且isinstance(e,e)為真,那麼這個處理器就能捕捉并處理異常e。舉例說,如果運作中引發了一個rationalerror異常,某個處理器頭部列出了rationalerror,或者valueerror,或者exception,該處理器都能捕捉這個異常。當然,比對valueerror的處理器還能捕捉和處理其他異常,比對exception的處理器能捕捉和處理各種主要異常。

運作中的異常可能發生在子產品層面的語句的執行中,更多情況是發生在某個函數的執行中。假設在函數f的執行中發生異常e,目前執行立即中斷,解釋器轉入異常處理模式,設法找到處理e的處理器。有關查找過程如下:

首先在發生異常的函數體裡查找處理器:

如果發生異常的語句位于一個try語句體裡,首先順序檢查這個try語句後部的各except子句,檢查是否存在能處理e的處理器。

如果發生異常的try語句的所有異常處理器都不能處理e,解釋器轉去檢視包圍着該try語句的外圍try語句(如果存在),檢查是否存在能與e比對的異常處理器。這個查找過程将在e發生的函數f裡逐層進行。

如果e不能在函數f裡處理,f的執行異常終止,e在函數f這次執行的調用點重新引發,導緻又一輪處理器查找工作。查找規則與上面一樣。

如果上面查找過程在某一步找到了與e比對的處理器,解釋器就轉去執行該except子句的體(異常處理器代碼)。執行完這段代碼後,解釋器回到正常執行模式,從該異常處理器所在的try語句之後繼續執行。

上述查找過程可能導緻函數一層層以異常方式退出,有可能一直退到目前子產品的最上層也沒有找到與之比對的處理器:

如果程式是在解釋器的互動方式下執行,python解釋器終止該子產品執行并回到互動狀态,輸出錯誤資訊後等待使用者的下一個指令。

如果程式是自主執行(或稱按批處理方式執行),該程式立即終止。

如果異常發生在主子產品的表層(不在任何函數裡),處理過程同樣如上所述。

在異常處理過程中還可能出現一些情況。例如,正在執行處理器代碼時又發生了新異常;或者進行中遇到某些特殊情況,需要引發新的異常。python語言裡還有關于這些情況的細節規定,這裡就不繼續讨論了。

python語言定義了一套标準異常類,它們都是baseexception的派生類,其最重要子類是exception,标準異常類都是exception的直接或間接派生類。

下面是一些常見異常,後面有些例子從其中一些異常派生自己的異常類:

這個圖并不完全,還有一些被分類為“警告”(warning)的異常等。