Python筆記(3)異常處理
Exception(異常)
當遇到異常的條件時,Python使用exception物件來描述。當遭遇一個錯誤的時候,程式就丟擲一個異常,如果沒有來處理此類異常的策略的話,程式將會以一個traceback的方式終止,程式碼如下:
>>> 1/0
Traceback (most recent call last):
File "<stdin>", line 1, in ?
ZeroDivisionError: integer division or modulo by zero
每個異常都是一個類的例項(上例中是ZeroDivisionError),有許多方法來丟擲和捕捉異常,最好要處理這些異常,而不是讓程式崩潰。
丟擲異常
>>> raise Exception
Traceback (most recent call last):
File "<stdin>", line 1, in ?
Exception
>>> raise Exception('hyperdrive overload')
Traceback (most recent call last):
File "<stdin>", line 1, in ?
Exception: hyperdrive overload
列出所有的Python自帶的異常型別
>>> import exceptions
>>> dir(exceptions)
['ArithmeticError', 'AssertionError', 'AttributeError', ...]
這些異常都可以用raise語句丟擲
>>> raise ArithmeticError
Traceback (most recent call last):
File "<stdin>", line 1, in ?
ArithmeticError
Class Name | Description |
Exception | The base class for all exceptions |
AttributeError | Raised when attribute reference or assignment fails |
IOError | Raised when trying to open a nonexistent file (among other things) |
IndexError | Raised when using a nonexistent index on a sequence |
KeyError | Raised when using a nonexistent key on a mapping |
NameError | Raised when a name (variable) is not found |
SyntaxError | Raised when the code is ill-formed |
TypeError | Raised when a built-in operation or function is applied to an object of the wrong type |
ValueError | Raised when a built-in operation or function is applied to an object with the correct type, but with an inappropriate value |
ZeroDivisionError | Raised when the second argument of a division or modulo operation is zero |
定義自己的異常類
class SomeCustomException(Exception): pass
捕獲異常
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!"
在函式中丟擲的異常,可以傳遞到呼叫它的地方之外,如果函式不能捕獲異常,那麼這個異常則會像冒泡一樣,一直傳遞到程式的頂端,這意味著,try/catch語句可以處理其他函式的異常。
如果一個異常,無法處理,可以利用raise語句繼續將它丟擲交給其他的地方來捕獲。如下程式碼:
class MuffledCalculator:
muffled = False
def calc(self, expr):
try:
return eval(expr)
except ZeroDivisionError:
if self.muffled:
print 'Division by zero is illegal'
else:
raise
全部的當muffled值為True和false的程式碼如下:
class MuffledCalculator:
muffled = False
def calc(self, expr):
try:
return eval(expr)
except ZeroDivisionError:
if self.muffled:
print 'Division by zero is illegal'
else:
raise
捕獲多個異常
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!"
except TypeError:
print "That wasn't a number, was it?"
如果對多個異常有相同的處理方法,可以把多個異常整合到一個程式碼塊中,而異常則都放在一個tuple中:
try:
x = input('Enter the first number: ')
y = input('Enter the second number: ')
print x/y
except (ZeroDivisionError, TypeError, NameError):
print 'Your numbers were bogus...'
如果你想在except語句中訪問異常物件,只需要將引數改變成兩個就可以了,如下。當你想在捕獲多個異常的時候,不影響系統,而又想將錯誤記錄在log檔案的話,這個方法很有用。
try:
x = input('Enter the first number: ')
y = input('Enter the second number: ')
print x/y
except (ZeroDivisionError, TypeError), e:
print e
注意, Python 3.0中,要寫成這個樣子
except (ZeroDivisionError, TypeError) as e.
如果你想要捕獲所有的錯誤,那麼你可以這樣寫:
ry:
x = input('Enter the first number: ')
y = input('Enter the second number: ')
print x/y
except:
print 'Something wrong happened...'
但是這樣做風險很大,因為它會忽略一切異常,比如Control+C的手動結束,sys.exit(),等等。所以,做好將它寫成如下的形式:
except Exception, e
然後對e進行某些檢測。
某些情況下,如下程式碼可以讓程式一直正確執行,直到碰到異常
try:
print 'A simple task'
except:
print 'What? Something went wrong?'
else:
print 'Ah... It went as planned.'
如下的程式碼表示,只有沒有異常的情況下程式才會結束,如果有異常,則輸出是什麼異常
while True:
try:
x = input('Enter the first number: ')
y = input('Enter the second number: ')
value = x/y
print 'x/y is', value
except Exception, e:
print 'Invalid input:', e
print 'Please try again'
else:
break
finally語句
finally語句在發生異常的時候才執行,一半是用來處理後事的^ ^
x = None
try:
x = 1/0
finally:
print 'Cleaning up...'
del x
finally語句中的東西在程式崩潰前執行
你也可以將這四個東西放在同一個語句快中
try:
1/0
except NameError:
print "Unknown variable"
else:
print "That went well!"
finally:
print "Cleaning up."