我们先通过一个例子来了解代码中引入异常处理的原因。
- print('Start')
- a=10
- b=0
- print(a/b)
- print('End')
执行结果
Traceback(most recent call last):
File"C:/Users/Kevin/PycharmProjects/PyDemo/p1/exception_demo.py", line 4,in print(a/b)
ZeroDivisionError:division by zero
Start
Processfinished with exit code 1
大家可以看到代码出现了问题,这个结果是可以预见的,但是End并没有成功打印,这说明了print('End')语句没有被执行,所以程序中一旦出现了异常,那么异常点后面的语句是不会被执行的!
我们可以利用条件语句来解决这个问题,代码如下:
- print('Start')
- a=10
- b=0
- if b!=0:
- print(a/b)
- print('End')
我们也可以通过python的异常处理机制来解决这个问题。在python中捕捉异常可以使用try/except语句。 try/except语句用来检测try语句块中的错误,从而让except语句捕获异常信息并处理。语法:try....except的语法,代码如下:
- print('Start')
- try:
- a=10
- b=0
- print(a / b)except:
- print("catch exception")
- print('End')
运行结果
Start
catch exception
End
大家可以看到try中的代码print(a / b)出了异常被except捕获,然后执行了print("catch exception"),最后程序正常执行完毕!
讲到这里可能有的同学会问,明明可以用条件语句就可以解决的问题,为什么还要引入异常机制呢?最简单的解释就是,用异常机制会大大的减少代码量,这个例子比较简单大家可能体会不到,在实际编码中try里面是会有很多行代码的,只要有错误那么就会被catch住!如果使用条件语句,那么就需要在多行代码中都进行判断,这个代码量可想而知!
异常的类型
异常也是分种类的,处理不同类型的错误,会使用不同的异常类型,python的标准异常包括:
- BaseException 所有异常的基类
- SystemExit 解释器请求退出
- KeyboardInterrupt 用户中断执行
- Exception 常规错误的基类
- StopIteration 迭代器没有更多的值
- GeneratorExit 生成器(generator)发生异常来通知退出
- StandardError 所有的内建标准异常的基类
- ArithmeticError 所有数值计算错误的基类
- FloatingPointError 浮点计算错误
- OverflowError 数值运算超出最大限制
- ZeroDivisionError 除(或取模)零 (所有数据类型)
- AssertionError 断言语句失败
- AttributeError 对象没有这个属性
- EOFError 没有内建输入,到达EOF 标记
- EnvironmentError 操作系统错误的基类
- IOError 输入/输出操作失败
- OSError 操作系统错误
- WindowsError 系统调用失败
- ImportError 导入模块/对象失败
- LookupError 无效数据查询的基类
- IndexError 序列中没有此索引(index)
- KeyError 映射中没有这个键
- MemoryError 内存溢出错误(对于Python 解释器不是致命的)
- NameError 未声明/初始化对象 (没有属性)
- UnboundLocalError 访问未初始化的本地变量
- ReferenceError 弱引用(Weak reference)试图访问已经垃圾回收了的对象
- RuntimeError 一般的运行时错误
- NotImplementedError 尚未实现的方法
- SyntaxErrorPython 语法错误
- IndentationError 缩进错误
- TabErrorTab 和空格混用
- SystemError 一般的解释器系统错误
- TypeError 对类型无效的操作
- ValueError 传入无效的参数
- UnicodeErrorUnicode 相关的错误
- UnicodeDecodeErrorUnicode 解码时的错误
- UnicodeEncodeErrorUnicode 编码时错误
- UnicodeTranslateErrorUnicode 转换时错误
- Warning 警告的基类
- DeprecationWarning 关于被弃用的特征的警告
- FutureWarning 关于构造将来语义会有改变的警告
- OverflowWarning 旧的关于自动提升为长整型(long)的警告
- PendingDeprecationWarning 关于特性将会被废弃的警告
- RuntimeWarning 可疑的运行时行为(runtime behavior)的警告
- SyntaxWarning 可疑的语法的警告
- UserWarning 用户代码生成的警告
使用不同类别的异常无法捕获非自身种类的异常,例如使用IOError是无法捕获ZeroDivisionError的,代码如下:
- print('Start')
- try:
- a=10
- b=0
- print(a / b)except IOError:
- print("catch exception")
- print('End')
运行结果
Start
Traceback (most recent calllast):
File"C:/Users/Kevin/PycharmProjects/PyDemo/p1/exception_demo.py", line 5,in
print(a / b)
ZeroDivisionError: division byzero
使用except可以带多种异常类型,
try:
正常的操作
......................
except(Exception1, Exception2,...ExceptionN):
发生以上多个异常中的一个,执行这块代码
......................
try...except BaseExceptionas msg: 输出异常信息.例如:
- print('Start')
- try:
- a =10
- b = 0
- print(a / b)except BaseException as msg:
- print(msg)print('End')
输出:
Start
division by zero
End
try...except...finally
该语句的含义是无论是否发生异常都将执行最后finally中的代码。示例代码如下:
- print('Start')
- try:
- a =10
- b = 0
- print(a / b)except :
- print('exception')
- finally:
- print("finally")
- print('End')
输出:
Start
exception
finally
End
抛出异常
raise语句允许程序员强制发生指定的异常。如果你需要确定是否引发了异常但不打算处理它时可以使用!例如:
- def exp_fuc():
- raise IOError
- exp_fuc()print('End')
运行结果
Traceback(most recent call last):
File"C:/Users/Kevin/PycharmProjects/PyDemo/p1/except_demo2.py", line 7,in
exp_fuc()
File"C:/Users/Kevin/PycharmProjects/PyDemo/p1/except_demo2.py", line 5,in exp_fuc
raise IOError
OSError
可以看到代码抛出了IOError,由于没有被捕获,所以print('End')没有被执行
自定义异常
程序可以通过创建新的异常类来命名它们自己的异常。异常通常应该直接或间接地从Exception类派生。
- def exp_fuc():
- raise IOError
- exp_fuc()print('End')
运行结果
Myexception: my error