一, 为什么使用异常处理
当程序运行的时候出现了异常, 导致程序终止运行, 为了解决这种情况, 我们需要预先对可能出现的异常进行处理, 一旦出现这种异常, 就使用另一种方式解决问题, 还有就是错误信息是使用者没有必要看到的, 他们不需要知道内部错误的原因, 所以我们需要友好的显示错误信息, 这就需要用到异常处理.
二, 简单异常处理
在以下代码里, 首先获取用户输入的值, 然后到 try 代码块里, 在 try 代码块里的代码是收到保护的, 如果 try 中的代码发生了异常, 就会执行 except 中的代码.
在 try 中的代码, 如果某一句出现了错误, 则这一句下面的代码就不再执行, 直接执行 except 中的代码.
- inp = input('请输入内容:')
- try:
- num = int(inp)
- print(num)
- except Exception as e:
- print(e)
- print('数据类型转换失败!')
输出结果:
请输入内容: aaa
invalid literal for int() with base 10: 'aaa'
数据类型转换失败!
三, 异常处理分类
在上面的示例中, except 后面的 Exception 是一个包含有错误信息的类, 而这个 e 是创建的 Exception 的对象, 包含着错误信息, 比如下面的输出结果.
- li = []
- inp = input('请输入内容:')
- li[int(inp)]
输出结果:
请输入内容: aaa
- Traceback (most recent call last):
- File "C:/Users/Administrator/PycharmProjects/untitled1/Alexsel/gg.py", line 318, in <module>
- li[int(inp)]
- ValueError: invalid literal for int() with base 10: 'aaa'
这里的 ValueError 就是异常的一种, 接下来我们就了解一下 Python 中的常见的异常.
异常 | 描述 |
---|---|
NameError | 尝试访问一个没有声明的变量 |
ZeroDivisionError | 除数为 0 |
SyntaxError | 语法错误 |
IndexError | 索引超出序列范围 |
KeyError | 请求一个不存在的字典关键字 |
IOError | 输入输出错误(比如要读的文件不存在) |
AttrilbuteError | 尝试访问未知的对象属性 |
ValueError | 传给函数的参数类型不正确,比如给 int()函数传入字符串 |
ImportError | 无法引入模块或包,大部分是路径或者名称错误 |
IndentationError | 语法错误,比如代码没有正确对齐 |
KeyboardInterrupt | Ctrl+C 正被按下 |
TypeError | 传入对象类型与要求的不符合 |
UnboundLocalError | 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量, 导致你以为正在访问它 |
四, 异常的分类处理
一个程序运行的时候可能出现多种异常, 常见的异常我们在上面都展示给大家了, 每种异常都可以根据类型捕捉到, 比如出现了 ValueError 类型的错误, 我们可以使用 ValueError 进行捕捉, 其它类型的异常就无法捕捉到, 我们可以针对出现的那些异常进行分类处理, 以便更好的处理异常.
- li = []
- inp = input('请输入内容:')
- try:
- li[int(inp)]
- except IndexError as ie:
- print('索引错误')
- except ValueError as ve:
- print('参数类型不正确')
输出结果:
请输入内容: aaa
参数类型不正确
如果我们不想那么麻烦, 想直接捕捉所有类型的异常怎么办, 那么我们就使用 Exception.
- li = []
- inp = input('请输入内容:')
- try:
- li[int(inp)]
- except Exception as e:
- print(e)
输出结果:
请输入内容: aaa
invalid literal for int() with base 10: 'aaa'
如果想同时使用 Exception 和单个类型异常捕捉, 应该吧单个类型异常的捕捉放到 Exception 的后面, 因为 Exception 放在前面则直接使用这个捕捉所有的错误, 下面的异常处理不再执行.
之前我们说到 Exception 是一个类, 我们刚才有讲了单个异常处理, 例如 ValueError,NmaeError 等, 这些异常都是 Exception 的派生类.
五, 完整的异常处理结构
- try:
- pass
- except ValueError as e:
- #当 try 中发生 ValueError 异常的时候, 执行这里的代码
- pass
- except Exception as e:
- pass
- else:
- #try 中没有出现异常执行这里的代码
- pass
- finally:
- #最终, 无论什么情况, 最后都执行这里的代码
- pass
执行流程
如果 try 中的代码出现错误, 首先判断是不是 ValueError 错误, 如果是执行, 不是执行 Exception 中的错误处理代码, 最终执行 finally 中的代码.
如果 try 中的代码没有出现错误, 就行 else 中的代码, 最终执行 finally 中的代码.
六, 主动触发异常
之前我们出现的错误都是解释器触发的, 我们想要自己触发一个异常需要怎么做, 这里我么就要使用到 raise.
- try:
- print('alexsel')
- raise Exception('出错了!!!')# 这里就是创建了一个 Exception 对象, 下面的 e 就是这个对象
- except Exception as e:
- print(e)
输出结果:
alexsel
出错了!!!
这里的自己触发的错误以及自定义的错误信息, 就直接传递到相应错误类型创建的对象中, 在这里就传递到了 e 中, 这个 e 就是封装了错误信息的一个对象.
这里我们就针对这个对象, 再讲一个类中的特殊成员__str__.
我们之前说到 Exception 是一个类, 我们刚才使用类 Exception('出错了!!') 创建了一个对象, 然后这个对象就传递给了 e, 最后我们可以使用 print 将 e 的里包含的内容输出, 可是我们在对一般的对象输出时就不会输出信息, 只会出现该对象内存信息, 如下
- class Foo:
- def __init__(self):
- print('init')
- obj = Foo()
- print(obj)
输出结果:
- init
- <__main__.Foo object at 0x00000000027F1898>
但是我们在使用异常处理的时候, 创建的 e 也是一个对象, 为什么可以使用 print 打印出错误信息, 原因就是在错误处理的类中写了一个特殊的类成员__str__, 使用这个之后, 创建的使用 print 打印创建的对象就会输出__str__中返回值返回的内容.
- class Foo:
- def __init__(self,age):
- self.age = age
- def __str__(self):
- return self.age
- obj = Foo('99')
- print(obj)
输出结果:
99
这里创建对象的时候传入了 age, 在我们输出的时候, 输出了__str__中的返回值, 所以输出了 99.
七, 自定义异常处理代码
我们在刚才知道了 raise 的用法和为什么可以使用 print 打印出错误信息, 我们就可以使用这两个方法进行自定义异常处理代码, 我们就简单做一个例子.
- class MyException(Exception):
- def __init__(self,message):
- self.message = message
- def __str__(self):
- return self.message
- try:
- print('alexsel')
- raise MyException('我的异常处理!')
- except MyException as e:
- print(e)
输出结果:
alexsel
我的异常处理!
在这里需要注意一下, 我们自己写的异常处理的类需要继承 Exception, 只有这样我们才能成功在 raise 和 except 后面使用的时候成功调用.
来源: https://www.cnblogs.com/liudi2017/p/9386753.html