Python 异常
工作过程
while true:
try:
x = int(input("Please enter a number:"))
break
except ValueError:
print('非法数字')
try
语句的工作原理如下:
- 首先执行
try
子句; - 如果没有异常发生,则跳过
except
子句并完成try
语句的执行; - 如果在执行
try
语句时发生了异常,则跳过该子句剩下的部分,然后进行下面的异常匹配; - 找到匹配后,程序进入对应的
except
子句中执行语句,否则执行停止。
一个 try
语句可能有多个 except
子句,以指定不同异常的处理程序,但是except
子句最多只会执行一个。一个 except
子句可以将多个异常命名为带括号的元组,如:
except(RuntimeError,TypeError,ZeroDivisionError):
pass
继承规则
class B(Exception):
pass
class C(B):
pass
class D(C):
pass
for cls in [B, C, D]:
try:
raise cls()
except D:
print('D')
except C:
print('C')
except B:
print('B')
当 except
子句中的类和发生的异常是同一种或者是发生的异常的基类时,此 except
子句可以捕捉到异常;相反当 except
子句中的类是异常的子类时,此 except
子句无法捕捉到异常。上面例子输出B、C、D
。修改 except
子句类的顺序为B、C、D
,则新的例子输出为 B、B、B
。因为 B
是C、D
的基类,可以捕捉到 C、D
的异常,因此,B、C、D
引起的异常都进入到 except B
子句中。
所以说,当 try
语句引起的异常可能存在继承关系时,一定要注意 except
子句的顺序,子类 except
语句尽量放在前面,基类 except
语句尽量放在后面。
最后的 except
子句可以省略掉异常名,以用作通配符。但请谨慎使用,因为以这种方式很容易掩盖真正的变成错误!它还可用于打印错误消息,然后重新引发异常。
try except
语句有一个可选的 else
语句,在使用时必须放在所有的 except
子句后面。对于在 try
子句中不引发异常时必须执行的代码来说很有用。如:
for arg in sys.argv[1:]:
try:
f = open(arg,'r')
except OSError:
print('cannot open', arg)
else:
print(arg, 'has', len(f.readlines()), 'lines')
f.close()
使用 else
子句比向 try
子句添加额外的代码要好,因为它避免了意外捕获由try......except
语句保护的代码未引发的异常,即可能是else
子句引发的异常,使用 else
子句这样的写法更加的清楚。
抛出异常
raise NameError('HiThere')
raise
唯一的参数就是要抛出的异常,这个参数必须是一个异常实例或者异常类。如果是异常类,它将通过调用没有参数的构造函数来隐式实例化。
如果不对异常进行处理,则可以使用更简单的 raise
语句重新引发异常。
try:
raise NameError('HiThere')
except NameError:
print('An exception flew by!')
raise
try:
raise
except NameError:
print(123)
这种情况下,raise
会引发 RuntimeError
。
用户自定义的异常
用户创建的异常必须直接或者间接地继承基类异常BaseException
。
finally 子句
try:
<>
except Error:
<>
else:
<>
finally:
<>
finally
子句将作为 try
语句结束前的最后一项任务被执行。finally
子句不论 try
语句是否产生了异常都会被执行。
以下是 finally
会遇到的几种情况:
- 执行
try
子句引发异常:
该异常可被
except
子句处理,如果没有被处理,则在finally
语句重新被引发。
- 在
except
和else
子句中出现异常:
该异常会在
finally
子句之后被重新引发。
如果 finally
子句中包含一个 return
语句,则返回值将来自 finally
子句的 return
返回值,而非来自 try
子句的 return
返回值。
例如:
>>>def bool_return():
... try:
... return True
... finally:
... return False
>>>bool_return()
False
一个更加复杂的例子:
def int_return(x, y):
try:
result = x/y
except ZeroDivisionError:
return 1
else:
return 2
finally:
return 3
>>>int_return(2, 1)
3
>>>int_return(2, 0)
3
在实际应用程序中,finally
对释放外部资源(如文件或者网络连接)非常有用,无论是否成功使用资源。