8.1 什麼是異常
python用異常對象來表示異常情況。遇到錯誤後,會引發異常。如果異常對象并未被處理或捕捉,程式就會用所謂的回溯(一種錯誤資訊)終止執行:
>>>1/0
報錯
如果這些錯誤資訊就是異常的全部功能,那麼它也就不必存在了。事實上,每個異常都是一個類的執行個體,這些執行個體可以被引發,并且可以用很多種方法進行捕捉,使得程式可以捉住錯誤并且對其進行處理,而不是讓整個程式失敗。
8.2.1 raise 語句
為了引發異常,可以使用一個類(exception的子類)或者執行個體參數調用raise語句。使用類時,程式自動建立執行個體。下面的例子,使用了内建的exception異常類:
>>>raise Exception
普通異常
>>>raise Exception('abc')
報abc異常錯誤
可以使用dir函數列出子產品的内容
>>>import exceptions
>>>dir(exceptions)
['ArithmeticError','AssertionError','AttributeError',...]
所有這些異常都可以用在raise中
>>>raise ArithmeticError
8.2. 自定義異常類
class SomeCustomException(Exception):pass
8.3 捕捉異常
try:
x = input('Enter the first number:')
y = input('Enter the second number:')
print x/y
except ZeroDivisionError:
print "The second number can't be zero"
如果沒有捕捉異常,它就會被傳播到調用的函數中。如果在那裡依然沒有捕獲,這些異常就會浮到程式的最頂層。也就是說你可以捕捉到在其他人的函數中所引發的異常。
class MuffledCalculator:
muffled = False
def calc(self,expr):
return eval(expr)
if self.muffled:
print 'Division by zero is illegal'
else:
raise
捕捉到了異常,但是又想重新引發它(傳遞異常),可以使用不帶參數的raise語句。
下面是這個類的用法示例,分别打開和關閉了屏蔽:
>>>calculator = MuffledCalculator
>>>calculator.calc('10/2')
5
>>>calculator.calc('10/0')
>>>calculator.muffled = True
當電腦沒有打開屏蔽機制時,ZeroDivisionError被捕捉但已傳遞了。
8.4 不止一個except 子句
print 2/'0'
print '除數不能為0'
except Exception:
print '其他類型異常'
8.5 用一個塊捕捉兩個異常
如果需要用一個塊捕捉多個異常,那麼可以将它們作為元組列出:
except (ZeroDivisionError,TypeError):
print '發生了一個異常'
8.6 擷取異常
except (ZeroDivisionError,Exception) as e:
print e
在python3.0中,except子句會被寫作except(ZerDivisionError,TypeError) as e.
8.7 捕捉所有異常
except:
print 'Something wrong happened。。'
這樣做是危險的,因為它會隐藏所有程式員未想到并且未做好準備處理的錯誤。
8.8 運用循環在異常
print 'A simple task'
print 'What? Something went weong?'
print 'Ah...It went as planned.'
使用else子句:
while True:
value = x/y
print 'x/y is',value
print 'Invalid input,Please try again.'
break
這裡的循環隻在沒有異常處理的情況下才會退出。換句話說,隻要發生錯誤,程式會不斷要求重新輸入。
可以使用空的except子句來捕捉所有Exception類的異常(也會捕捉其所有子類的異常)。百分之百捕捉到所有的異常時不可能的,因為try/except語句中的代碼可能會出問題,比如使用舊風格的字元串異常或自定義的異常類不是Exception類的子類。不過如果需要使用except Exception的話,可以使用列印的方法來顯示錯誤資訊:
except Exception,e:
print 'Invalid input:',e
print 'Please try again'
8.9 finally 子句
最後finally子句,它可以用來在可能的異常後進行清理。它和try子句聯合使用:
x = None
x = 1/0
finally:
print 'Cleaning up...'
del x
上面的代碼中,finally子句肯定會被執行,不管子句try子句中是否發生異常。
使用del語句删除一個變量是非常不負責的清理手段,是以finally子句用于關閉檔案或者網絡套接字時會非常有用。還可以在同一條語句中組合使用try,except,finally和else。
1/0
except NameError:
print "Unknown variable"
print "That went well!"
print "Cleaning up."
8.10 異常和函數
如果異常在函數内引發而不被處理,它就會傳播至函數調用的地方。如果在那裡也沒有處理異常,它就會繼續傳播,一直到達主程式(全局作用域)。如果那裡沒有異常處理程式,程式會帶着堆棧跟蹤中止:
>>>def faulty()
raise Exception('Something is wrong')
>>>def ignore_exception():
faulty()
>>>def handle_exception():
print 'Exception handled'
>>>ignore_exception()
>>>handle_exception()
Exception handled
可以看到,faulty中産生的異常通過faulty和ignore_exception傳播,最終導緻了堆棧跟蹤。同樣的,它也傳播到了handle_exception,但在這個函數中被try/except語句處理.
8.11 異常之禅
def describePerson(person):
print 'Description of',person['name']
print 'Age:',person['age']
print 'Occupation:' + person['occupation']
except KeyError: pass
這裡在列印職業時使用加号而不是逗号,否則字元串'Occupation:'在異常引發之前就會被輸出。
這個程式直接假定'occupation'鍵存在。如果他的确存在,那麼就會省事一些。直接取出值在列印出即可。不用額外檢查它是否真的存在。如果該鍵不存在,則會引發KeyError異常而被except子句捕捉到。
檢視對象是否存在特定特性時:
obj.write
except AttributeError:
print 'The object is not writeable'
print 'The object is writeeable'
本文轉自潘闊 51CTO部落格,原文連結:http://blog.51cto.com/pankuo/1661442,如需轉載請自行聯系原作者