0.最重要的内置異常
Exception:所有異常的基類
AttributeError:屬性引用或指派異常
IOError:試圖讀、寫不存在的檔案
IndexError:使用Sequence中不存在的Index
KeyError:使用Mapping中不存在的Key
NameError:變量名未找到
SyntaxError:文法錯
TypeError:在内置函數中使用錯誤的類型
ValueError:類型對,但值不正确
ZeroDivisionError:除零
1.自定義異常
class SomeCustomException(Exception): pass
2.捕獲異常
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!"
#适合于人機互動
3.無參數raise重新抛出異常reraises
class MuffledCalculator:
muffled = 0
def calc(self, expr):
try:
return eval(expr)
except ZeroDivisionError:
if self.muffled:
print 'Division by zero is illegal'
else:
raise
#适合于程式間互動
#注意在除以零且muffled不為零的情況下,程式的傳回值為None
4.多Exception分支
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?"
5.在一句中同時捕獲多個Exception
try:
x = input('Enter the first number: ')
y = input('Enter the second number: ')
print x/y
except (ZeroDivisionError, TypeError): #前後的括号實際上起到了組裝成Tuple的作用
print 'Your numbers were bogus...'
6.同時捕獲多個,而且能甄别具體是哪個
try:
x = input('Enter the first number: ')
y = input('Enter the second number: ')
print x/y
except (ZeroDivisionError, TypeError), e: #e指代實際被捕獲的那個
print e
7.捕獲一切異常
try:
x = input('Enter the first number: ')
y = input('Enter the second number: ')
print x/y
except:
print 'Something wrong happened...'
但這種捕獲方式比較危險,因為它會忽略程式中你未曾想到的錯誤,同時也不能針對錯誤來處理,是以盡量采用以下形式來捕獲所有異常:
try:
x = input('Enter the first number: ')
y = input('Enter the second number: ')
print x/y
except Exception, e:
print e #Or do something about e
8.When All Is Well
不知咋翻,多用于輸入時,不斷提示輸入直到一切就緒
while 1:
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
9.finally
在出現可能的異常之後做一些清理工作
x = None #初始化x是因為否則 del x 會引發異常
try:
x = 1/0
finally:
print 'Cleaning up...'
del x
結果為:--->
Cleaning up...
Traceback (most recent call last):
File "C:/python/div.py", line 4, in ?
x = 1/0
ZeroDivisionError: integer division or modulo by zero
也可以加上except:
x = None
try:
x = 1/0
except Exception, e:
print e
finally:
print 'Cleaning up...'
del x
結果為: --->
integer division or modulo by zero
Cleaning up...
10.異常跟蹤
如果一個異常在函數A内部被引發,但沒有被處理,它将被傳遞給調用它的函數B,如果在B處又未處理,它将繼續上溯傳遞,直到全局域内的函數G,如果在G中仍未被處理,整個程式将halt并顯示錯誤資訊(a stack trace):
def faulty():
raise Exception('Something is wrong')
def ignore_exception():
faulty()
def handle_exception():
try:
faulty()
except:
print 'Exception handled'
ignore_exception() --->
Traceback (most recent call last):
File '<stdin>', line 1, in ?
File '<stdin>', line 2, in ignore_exception
File '<stdin>', line 2, in faulty
Exception: Something is wrong
handle_exception() --->
Exception handled #隻要在任何一處被處理了,則整個程式不被因為此Exception而Halt。
11.The Zen of Exceptions - Exception哲理
比較下面兩段代碼:
def describePerson(person):
print 'Description of', person['name']
print 'Age:', person['age']
if 'occupation' in person:
print 'Occupation:', person['occupation']
def describePerson(person):
print 'Description of', person['name']
print 'Age:', person['age']
try: print 'Occupation:', person['occupation']
except KeyError: pass
其中第一段會查找Key “occupation”兩次,一次判斷,一次取值;而第二段代碼則隻要一次。
但在大多數情況下,用try/exception還是if/else隻是個人喜好的不同(a matter of taste)。對性能的影響不大,而且程式設計時對性能的考慮是第二位的。
The point is that using a try/except statement is in many cases much more natural (more “Pythonic”) than if/else。應該盡量使用它。
最後引用Grace Hopper's words of wisdom, “It’s easier to ask forgiveness than permission.”
這種政策叫Leap Before You Look idiom.