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.