python异常处理,通过编程处理选择的异常是可行的。看一下下面的例子:它会一直要求用户输入,直到输入一个合法的整数为止,但允许用户中断这个程序(使用 Control-C
或系统支持的任何方法)。注意:用户产生的中断会引发一个 KeyboardInterrupt 异常:
>>> while True: ... try: ... x = int(raw_input("Please enter a number: ")) ... break ... except ValueError: ... print "Oops! That was no valid number. Try again..." ...
try 语句按如下方式工作:
- 首先,执行 try 子句(在 try 和 except 关键字之间的部分)。
- 如果没有异常发生,except 子句在 try 语句执行完毕后就被忽略了。
- 如果在 try 子句执行过程中发生了异常,那么该子句其余的部分就会被忽略。如果异常匹配于 except 关键字后面指定的异常类型,就执行对应的 except 子句。然后继续执行 try 语句之后的代码。
- 如果发生了一个异常,在 except 子句中没有与之匹配的分支,它就会传递到上一级 try 语句中。如果最终仍找不到对应的处理语句,它就成为一个 未处理异常,终止程序运行,显示提示信息。
一个 try 语句可能包含多个 except 子句,分别指定处理不同的异常。至多只会有一个分支被执行。异常处理程序只会处理对应的 try 子句中发生的异常,在同一个 try 语句中,其他子句中发生的异常则不作处理。一个 except 子句可以在括号中列出多个异常的名字,例如:
... except (RuntimeError, TypeError, NameError): ... pass
注意,此元组周围的括号是必需的,因为 except ValueError, e:
是旧式的写法,在现代 Python 中通常写成 except ValueError, e:
(如下所述)。为了保持向后兼容性,旧式语法仍然是支持的。这意味着 except RuntimeError, TypeError
不等同于 except (RuntimeError, TypeError):
而等同于 except RuntimeError as TypeError:
, 这应该不是你想要的。
最后一个 except 子句可以省略异常名称,以作为通配符使用。你需要慎用此法,因为它会轻易隐藏一个实际的程序错误!可以使用这种方法打印一条错误信息,然后重新抛出异常(允许调用者处理这个异常):
import sys try: f = open('myfile.txt') s = f.readline() i = int(s.strip()) except IOError as e: print "I/O error({0}): {1}".format(e.errno, e.strerror) except ValueError: print "Could not convert data to an integer." except: print "Unexpected error:", sys.exc_info()[0] raise
try … except 语句可以带有一个 else子句 ,该子句只能出现在所有 except 子句之后。当 try 语句没有抛出异常时,需要执行一些代码,可以使用这个子句。例如
for arg in sys.argv[1:]: try: f = open(arg, 'r') except IOError: print 'cannot open', arg else: print arg, 'has', len(f.readlines()), 'lines' f.close()
使用 else 子句比在 try 子句中附加代码要好,因为这样可以避免 try … except 意外的截获本来不属于它们保护的那些代码抛出的异常。
发生异常时,可能会有一个附属值,作为异常的 参数 存在。这个参数是否存在、是什么类型,依赖于异常的类型。
在异常名(列表)之后,也可以为 except 子句指定一个变量。这个变量绑定于一个异常实例,它存储在 instance.args
的参数中。为了方便起见,异常实例定义了 __str__() ,这样就可以直接访问过打印参数而不必引用 .args
。这种做法不受鼓励。相反,更好的做法是给异常传递一个参数(如果要传递多个参数,可以传递一个元组),把它绑定到 message 属性。一旦异常发生,它会在抛出前绑定所有指定的属性:
>>> try: ... raise Exception('spam', 'eggs') ... except Exception as inst: ... print type(inst) # the exception instance ... print inst.args # arguments stored in .args ... print inst # __str__ allows args to be printed directly ... x, y = inst.args ... print 'x =', x ... print 'y =', y ... <type 'exceptions.Exception'> ('spam', 'eggs') ('spam', 'eggs') x = spam y = eggs
对于那些未处理的异常,如果一个它们带有参数,那么就会被作为异常信息的最后部分(“详情”)打印出来。
异常处理器不仅仅处理那些在 try 子句中立刻发生的异常,也会处理那些 try 子句中调用的函数内部发生的异常。例如:
>>> def this_fails(): ... x = 1/0 ... >>> try: ... this_fails() ... except ZeroDivisionError as detail: ... print 'Handling run-time error:', detail ... Handling run-time error: int division or modulo by zero