1、什么是异常
python使用异常对象
来表示异常状态,并在遇到错误时引发异常。异常对象未被处理或捕获时,程序将终止并显示一条错误消息(traceback)。如下:
>>> 1/0
Traceback(most recent call last):
File"<stdin>", line 1, in?
ZeroDivisionError.integer division or modulo by zero
每个异常都是某个类(如ZeroDivisionError)的实例,我们可以以各种方式引发和捕获这些实例,从而逮住错误并采取措施,而不是放任整个程序失败。
2、引发和创建异常
raise语句引发异常:将一个类(必须是Exception的子类)或实例作为参数。
raise Exception # 将类作为参数时,将自动创建一个实例。这里引发的是通用异常,没有指出出现了什么错误。
raise Exception('hyperdrive overload') # 添加了错误消息hyperdrive overload
比较重要的一些内置的异常类:
Exception:几乎所有的异常类都是从它派生而来的
AttributeError:引用属性或给他赋值失败时引发
OSError:操作系统不能执行指定的任务(如打开文件)时引发,有多个子类
indexError:使用序列中不存在的索引时引发,为LookupError的子类
KeyError:使用映射中不存在的键时引发,为LookupError的子类
NameError:找不到名称(或变量)时引发
SyntaxError:代码不正确时引发
TypeError:将内置操作或函数用于类型不正确的对象时引发
ValueError:将内置操作或函数用于这样的对象时引发:其类型正确但包含的值不合适
ZeroDivisionError:在除法或求模运算的第二个参数为0时引发
3、捕获异常
异常有趣的地方是可对其进行处理,称之为捕获异常。常用:try/except语句。基本用法:
# 一:捕获异常并对错误进行处理(打印友好的错误消息)
try:
x = int(input('first number:'))
y = int(input('second number:'))
print(x / y)
except ZeroDivisionError:
print("the second number can't be zero!")
# 二:捕获异常后,抑制异常
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
# 注意:发生除零行为,若启用抑制功,calc将隐式地返回None。
# 三:在except子句中,引发别的异常
try:
1 / 0
except ZeroDivisionError:
raise ValueError # 进行except子句的异常将被作为异常上下文存储起来,并出现在最终的错误消息中
# 四:使用None来禁用上下文
try:
1 / 0
except ZeroDivisionError:
raise ValueError from None
# 执行结果如下:
Traceback(most recent call last):
File"<stdin>", line 3, in <module>
ValueError
其他用法:
# 一、多个except子句,捕获多种异常
try:
x = int(input('first number:'))
y = int(input('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")
# 二、一个except子句捕获多个异常,可在元组中指定异常(一个参数)
try:
x = int(input('first number:'))
y = int(input('second number:'))
print(x / y)
except (ZeroDivisionError, TypeError, NameError):
print("your numbers were bogus ...")
# 三、捕获异常对象本身(可使用两个参数)
try:
x = int(input('first number:'))
y = int(input('second number:'))
print(x / y)
except (ZeroDivisionError, TypeError) as e:
print(e) # 打印异常并继续运行
# 四、捕获所有异常,在except中不指定任何异常类即可
try:
x = int(input('first number:'))
y = int(input('second number:'))
print(x / y)
except:
print('something wrong happened ...')
# 这种做法很危险,会捕获到用户使用ctrl+c或调用函数sys.exit来终止执行的企图等。推荐使用except Exception as e对异常对象进行检查。(可能会让不是从Exception派生而来的异常漏网,如SystemExit、KeyboardInterrupt,他们是从Exception的超类BaseException派生而来)
# 五、给try/except添加else子句和finally:没有出现异常时会执行else中代码块
x = None
try:
x = 1 / 0
except NameError:
print('unknown variable')
else:
print("that went well!")
finally:
print("cleaning up...")
del x # 发生异常时,执行finally子句清理工作(适用于确保文件或网络套接字等得以关闭)
4、异常之禅
很多情况下,相比使用if/else,使用try/except语句更自然,也更符合python风格。(直接去做,有问题在处理,而不是预先做大量的检查)