標籤:
1、基礎
try/except/else:【else是可選的】捕捉由代碼中的異常並恢複,匹配except裡面的錯誤,並執行except中定義的代碼,後繼續執行程式(發生異常後,由except捕捉到異常後,不會中斷程式,繼續執行try語句後面的程式)
try首行底下的代碼塊代表此語句的主要動作:試著執行的程式碼。except分句定義try代碼塊內引發的異常處理器,而else分句(如果有)則是提供沒有發生異常時候要執行的處理器。
try/finally: 無論異常是否發生,都執行清理行為 (發生異常時程式會中斷程式,只不過會執行finally後的代碼)
raise: 手動在代碼中接觸發異常。
assert: 有條件地在程式碼中觸發異常。 assert幾乎都是用來收集使用者定義的約束條件
with/as 在Python2.6和後續版本中實現環境管理器。
使用者定義的異常要寫成類的執行個體,而不是字串、。
finally可以和except和else分句出現在相同的try語句內、
擴充
try/except/finally
可以在同一個try語句內混合except和finally分句:finally一定回執行,無論是否有異常引發,而且不也不管異常是否被except分句捕捉到。finally有沒有異常都執行
try/except/else:
except捕捉到對應的異常才執行。else 沒有異常才執行、
也就是說except分句會捕捉try代碼塊執行時所有發生的任何異常,而else分句只在try代碼執行沒有發生異常時才執行,finally分句無法釋放發生異常都執行。
2、try語句分句形式
分句形式 說明
except: 捕捉所有(其他)異常類型
except name: 只捕捉特定的異常
except name,value: 捕捉所有的異常和其額外的資料(或執行個體)
except (name1,name2) 捕捉任何列出的異常
except (name1,name2),value: 捕捉任何列出的異常,並取得其額外資料
else: 如果沒有引發異常,就運行
finally: 總是會運行此代碼塊,無論是否發生異常
空的except分句會捕捉任何程式執行時所引發的而未被捕捉到的異常。要取得發生的實際異常,可以從內建的
sys模組取出sys.exc_info函數的調用結果。這會返回一個元組,而元組之前兩個元素會自動包含當前異常的名稱,
以及相關的額外資料(如果有)。就基於類的異常而言,這兩個元素分別對應的是異常的類以及引發類的執行個體。
sys.exc_info結果是獲得最近引發的異常更好的方式。如果沒有處理器正在處理,就返回包含了三個None值的元組。
否則,將會返回(type,value和traceback)
*type是正在處理的異常的異常類型(一個基於類的異常的類對象)
*value是異常參數(它的關聯值或raise的第二個參數,如果異常類型為類對象,就一定是類執行個體)
*traceback是一個traceback對象,代表異常最初發生時所調用的堆棧。
3、try/else分句
不要將else中的代碼放入try:中。保證except處理器只會因為封裝在try中代碼真正的失敗而執行,而不是為else中的情況行為失敗而執行。
else分句,讓邏輯封明確
4、try/finally分句
python先運行try: 下的代碼塊:
如果try代碼塊運行時沒有異常發生,Python會跳至finally代碼塊。然後整個try語句後繼續執行下去。
如果try代碼塊運行時有發生異常,Python依然會回來運行finally代碼塊,但是接著會把異常向上傳遞到較高的try語句或頂層的預設處理器。程式不會在try語句繼續執行。
try:
Uppercase(open(‘/etc/rc.conf‘),output).process()
finally:
open(‘/etc/rc.conf‘).close
5、統一try/except/finally分句
2.5版本後可統一(包括2.5版本)
try:
main-action:
except Exception1:
hander1
except Exception2:
hander2
...
else:
else-block
finally:
finally-block
這語句中main-action代碼會先執行。如果該程式碼(main-action)引發異常,那麼except代碼塊都會逐一測試,尋找與拋出的異常相符的語句。如果引發異常
的是Exception1則會執行hander1代碼塊,如果引發異常的是Exception2,則會執行hander2代碼塊。以此類推。如果沒有引發異常,將會執行else-block代碼塊。
無論前面發生什麼,當main-action代碼塊完成時。finally-block都會執行。
6、通過嵌套合并except和finally
try:
try:
main-action:
except Exception1:
hander1
except Exception2:
hander2
...
else:
else-block
finally:
finally-block
和5的效果一樣
7、raise語句
要故意觸發異常,可以使用raise語句。raise語句組成是: raise關鍵字,後面跟著要引發的異常名稱(選用),以及一個可選的額外的資料項目,後可隨著異常傳遞
raise <name>
raise <name>,<data>
raise
第二種形式隨著異常傳遞額外的資料項目,在raise語句中,資料是列在異常名稱的後面的;在try語句中,取得該資料是通過引入一個進行接收
它的變數實現的。例如,如果try引入一個exceptname,X:語句,則變數X就會被賦值為raise內所列出的額外的資料項目,如果沒有定義預設接受到
的就是特殊對象None。一旦被程式中任意的except分句捕捉,異常就死了(也就是說,不會傳遞給另一個try),除非又被另一個raise語句或
錯誤所引發。現在使用者定義的異常應該是類執行個體對象。
8、assert語句
assert可以有條件地在程式碼中觸發異常,可以認為是有條件的raise.
牢記:assert幾乎都是用來收集使用者定義的約束條件,而不是捕捉內在的程式設計錯誤。因為Python會自動收集程式的設計錯誤,通常沒有必要寫
assert去捕捉超出索引值,類型不符以及除數為0之類的事
該語句形式:
assert <test>,<data>
執行個體
>>> def f(x):
... assert x>0,‘x must be great zerot‘
... return x**2
二、異常對象
Python2.5版本 字串異常會產生‘deprecation‘(不建議使用)’警告。python3.0將不再支援字串異常,python2.7版本已經不再支援。
所有的異常都是基於類的異常,字串異常已退出曆史舞台。
1、基於類的異常
sys.exc_info() 一種抓取最近發生異常的常用方式。
對基於類的異常而言,其結果中第一個元素就是引發異常類,而第二個是實際引發的執行個體。
注意:目前Python的說明檔案指出,使用者定義的異常最好繼承自Exception內建的異常(但不是必須要求)
在try語句中,捕捉其超類就會捕捉這個類,以及類樹中超類下的所有子類:超類會變成異常分類的名稱,而子類會變成該分類中特定的
異常類型。使用異常的超類,這樣子類也捕捉到,可以在未來增加函數異常(在子類裡),而不影響程式。
Python2.5以後版本將每個異常都寫成類(必須),從異常樹頂層繼承Exception(非必須)。
基本原則是:在異常處理器中,通常來說具體要優於一般。
2、內建Exception類
Python把內建異常組織成層次,來支援各種捕捉模式
Exception: 異常的頂層根超類
StandardError: 所有內建錯誤異常的超類
ArithmeticError: 所有數值錯誤的超類
OverflowError: 識別特定的數值錯誤的子類
可以在Python庫手冊或exceptionsn模組的協助文本中查閱。
>>> import exceptions
>>> help(exceptions)
3、定義異常文本
對基於類的異常而言,其結果中第一個元素就是引發異常類,而第二個是實際引發的執行個體
>>> raise MyBad():
>>> raise MyBad()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
__main__.MyBad: <__main__.MyBad instance at 0x2850d26c>
這樣的顯示不友好。改進顯示,可以在類中定義__repr__或__str__顯示字串重載方法,從而返回異常達到想要預設處理器顯示字串。
>>> class MyBad():
... def __repr__(self):
... return "Sorry--my mistake!"
...
>>> raise MyBad()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
__main__.MyBad: Sorry--my mistake
這樣把顯示類的執行個體改為了我們定義的文本。
注意:如果繼承自內建異常類,錯誤測試會有細微的改變,構造方法參數會自動儲存並顯示在訊息中。【同樣也可以把繼承的重載】
>>> class MyBad(Exception):pass
... >>> raise MyBad()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
__main__.MyBad
>>> raise MyBad(‘the‘,‘bright‘,‘side‘,‘of‘)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
__main__.MyBad: (‘the‘, ‘bright‘, ‘side‘, ‘of‘)
4、發送額外資料和執行個體行為
把環境資訊附加在基於類的異常的辦法是:在引發的執行個體對象中填寫執行個體的屬性,通常是在類的構造器方法中。在異常處理器中,是列出
要賦值為引發的執行個體的變數,然後通過這個變數名來讀取附加的轉改資訊,並且調用任何基礎的類方法。【很強大的功能】
>>> class FormatError:
... def __init__(self,line,file):
... self.line=line
... self.file=file
>>> def parser():
... raise FormatError(42,file=‘diege.txt‘) #手動定義異常,基於類的異常,類建構函式傳遞兩個資料。
...
>>> try:
... parser()
... except FormatError,X: #定義接受異常(類的執行個體-異常引發時產生的執行個體)傳遞過來資料的變數。
... print ‘Error at‘,X.file,X.line #顯示執行個體傳遞過來的資料
...
Error at diege.txt 42
5、raise的一般形式
raise string #基於字串的異常,已淘汰
raise string,data #基於字串的異常,已淘汰
raise instance #最常用的模式,直接接一個執行個體:raise FormatError(42,file=‘diege.txt‘)
raise class,instance
raise
為了和內建異常為字串的的舊版相容,也可以
raise class #same as :raise class()
raise class,arg # same as :raise class(arg)
raise clase(arg1,arg2,...) #same as:raise class(arg1,arg2...)
這些都相當於raise class(arg),等效於raise instance形式
>>> def parse():
... raise FormatError,(42,‘diege.txt‘)
三、異常的設計
1、嵌套異常處理器
把內部的try寫成函數來嵌套
使用文法嵌套
2、異常的習慣使用者
1)異常不總是錯誤
3、核心語言總結
一般而言,Python提供了一個有層次的工具集。
內建工具:
像字串,列表和字典這些內建類型,會讓編寫程式更為迅速。
Python擴充:
就更重要的任務來說,可以編寫自己的函數,模組以及類來擴充Python
已編譯的擴充:
Python的工具箱類型。
分類 例子
物件類型 列表,字典,檔案和字串
函數 len,range,apply,open
異常 IdexError,KeyError
模組 os,TKinter,pickle,re
屬性 __dict__,__name__,__class__
外部工具 NumPY,SWIG,Jython,IronPython
Python學習筆記總結(四)異常處理