1. 程式人生 > >Python筆記(3)異常處理

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."