天天看點

python之異常

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,如需轉載請自行聯系原作者