一、错误和异常
1、程序中难免会出现错误,而错误分成两种:
1)语法错误(这种错误,程序过不了python解释器的语法检测,必须在程序执行前改正)
if a #缺少冒号
2)逻辑错误
res = 1/0 #报错,0不能为除数
l =[1,2]
l[4] #报错,超出边界
2.什么是异常
异常就是程序运行时发生错误的信号,在python中,错误发生的异常,例如;NameError TypeError ValueError等,这些都是异常。
异常是一个事件,改事件会在程序执行过程中发生,影响程序的正常执行,一般情况下,在python中无法处理程序时就会发生异常,异常时Python的一个对象,表示一个错误,当Python脚本发生异常时,我们需要捕获并处理异常,否则程序就会终止执行。
res = 1/0
print(res)
"""
异常信息
Traceback (most recent call last):
File "D:/Pycharm Community/面向对象/a.py", line 1, in <module>
res = 1/0
ZeroDivisionError: division by zero
"""
异常信息分为3个部分
1)异常追踪信息
raceback (most recent call last):
File "D:/Pycharm Community/面向对象/a.py", line 1, in <module>
res = 1/0
2)异常类
ZeroDivisionError
3)异常值
division by zero
二、异常种类
在python中不同的异常可以用不同的类型(python中统一了类与类型,类型即类)去标识,不同的类对象标识不同的异常,一个异常标识一种错误
异常名称 | 描述 |
AttributeError | 对象没有这个属性 |
IOError | 入/输出异常,基本上是无法打开文件,操作失败 |
BaseException | 所有异常的基类 |
SystemExit | 解释器请求退出 |
KeyboardInterrupt | 用户中断执行(通常是输入^C) |
StopIteration | 迭代器没有更多的值 |
GeneratorExit | 生成器(generator)发生异常来通知退出 |
StandardError | 所有的内建标准异常的基类 |
ArithmeticError | 所有数值计算错误的基类 |
FloatingPointError | 浮点计算错误 |
OverflowError | 数值运算超出最大限制 |
ZeroDivisionError | 除(或取模)零 (所有数据类型) |
AssertionError | 断言语句失败 |
EOFError | 没有内建输入,到达EOF 标记 |
EnvironmentError | 操作系统错误的基类 |
OSError | 操作系统错误 |
WindowsError | 系统调用失败 |
ImportError | 导入模块/对象失败 |
LookupError | 无效数据查询的基类 |
IndexError | 序列中没有此索引(index) |
KeyError | 映射中没有这个键 |
MemoryError | 内存溢出错误(对于Python 解释器不是致命的) |
NameError | 未声明/初始化对象 (没有属性) |
UnboundLocalError | 访问未初始化的本地变量 |
ReferenceError | 弱引用(Weak reference)试图访问已经垃圾回收了的对象 |
RuntimeError | 一般的运行时错误 |
NotImplementedError | 尚未实现的方法 |
SyntaxError | Python 语法错误 |
IndentationError | 缩进错误 |
TabError | Tab和空格混用 |
SystemError | 一般的解释器系统错误 |
TypeError | 对类型无效的操作 |
ValueError | 传入无效的参数 |
UnicodeError | Unicode 相关的错误 |
UnicodeDecodeError | Unicode 解码时的错误 |
UnicodeEncodeError | Unicode 编码时错误 |
UnicodeTranslateError | Unicode 转换时错误 |
DeprecationWarning | 关于被弃用的特征的警告 |
FutureWarning | 关于构造将来语义会有改变的警告 |
OverflowWarning | 旧的关于自动提升为长整型(long)的警告 |
PendingDeprecationWarning | 关于特性将会被废弃的警告 |
RuntimeWarning | 可疑的运行时行为(runtime behavior)的警告 |
SyntaxWarning | 可疑的语法的警告 |
UserWarning | 用户代码生成的警告 |
三、异常处理
1. 什么是异常处理
python解释器检测到错误,触发异常(也允许程序员自己触发异常)
程序员编写特定的代码,专门用来捕获这个异常(这段代码与程序逻辑无关,与异常处理有关)
日过捕获成功则进入另外一个处理分支,执行你为其定制的逻辑,是程序不会崩溃,这就是异常处理
2、为何要进行异常处理
python解释器去执行程序,检测到一个错误时,触发异常,异常触发后且没被处理的情况下,程序就在当前异常处终止,后面代码不会执行,谁会用一个运行真突然崩溃的软件。
所以你必须提供一种异常机制来增强你程序的健壮性欲容错性
3.如何进行异常处理
我们知道异常室友程序的错误引起的,语法上的错误跟异常处理无关,必须在程序运行前修正。
1)使用if判断格式
num1=input('>>: ') #输入一个字符串试试
if num1.isdigit():
int(num1) #我们的正统程序放到了这里,其余的都属于异常处理范畴
elif num1.isspace():
print('输入的是空格,就执行我这里的逻辑')
elif len(num1) == 0:
print('输入的是空,就执行我这里的逻辑')
else:
print('其他情情况,执行我这里的逻辑')
#第二段代码
# num2=input('>>: ') #输入一个字符串试试
# int(num2)
#第三段代码
# num3=input('>>: ') #输入一个字符串试试
# int(num3)
问题一:
使用if的方式我们只为第一段代码加上了异常处理,针对第二段代码,你得重新写一堆if,elif等
而这些if,跟你的代码逻辑并无关系,可读性差
问题二:
第一段代码和第二段代码实际上是同一种异常,都是ValueError,相同的错误按理说只处理一次就可以了,而用if,由于这二者if的条件不同,这只能逼着你重新写一个新的if来处理第二段代码的异常
第三段也一样
2)异常处理(try....except)
基本语法
try:
<语句> #运行别的代码
except <异常类型> as 别名:
<语句> #如果在try部份引发了'name'异常
except <异常类型> as 别名:
<语句> #如果引发了'name'异常,获得附加的数据
else:
<语句> #如果没有异常发生
异常类只能用来处理指定的异常情况,如果非指定异常则无法处理。(异常是由程序的错误引起的,语法上的错误跟异常处理无关,必须在程序运行前就修正)
try:
l=[1,2,3]
m=l[5] #IndexError
except ValueError as e:
print(e)
3)多分支
如果你想要的效果是,对于不同放入异常我们需要定制不同的处理逻辑,那么就需要用到多分支
try:
msg=input('>>:')
int(msg) #ValueError
l=[1,2,3]
m=l[5] #IndexError
except ValueError as e:
print(e)
except IndexError:
print('NameError')
except KeyError as e:
print(e)
4)万能异常(Exception)
在python的异常中,有一个万能异常:Exception,他可以捕获任意异常
try:
msg=input('>>:')
int(msg) #ValueError
l=[1,2,3]
m=l[5] #IndexError
except Exception as e:
print(e)
5)异常的其它机构
s1 = "1"
try:
int(s1)
except ValueError as e:
print(e)
except IndexError:
print('NameError')
except KeyError as e:
print(e)
else:
print("try内代码块没有异常则执行我")
print("后面逻辑----------->")
"""
try内代码块没有异常则执行我
后面逻辑----------->
"""
try-finally 语句
try-finally 语句无论是否发生异常都将执行最后的代码。无论是否异常,都会执行该模块,通常进行清理工作
s1 = "hello"
try:
int(s1)
except ValueError as e:
print(e)
except IndexError:
print('NameError')
except KeyError as e:
print(e)
else:
print("try内代码块没有异常则执行我")
finally:
print("无论是否异常,都会执行该模块,通常进行清理工作")
print("后面逻辑----------->")
"""
invalid literal for int() with base 10: 'hello'
无论是否异常,都会执行该模块,通常进行清理工作
后面逻辑----------->
"""
6)主动触发异常
try:
raise TypeError("类型错误")
except Exception as e:
print(e)
"""
类型错误
"""
7)自定义异常
class FooException(BaseException):
def __init__(self,msg):
self.msg=msg
print(FooException("自己定制的异常类"))
"""
自己定制的异常类
"""
使用try...except的方式
1.把错误处理和真正的工作分开了
2.代码更易组织,更清晰,复杂的工作任务更容易实现
3.更安全,不至于由于程序一些小的失误而使程序意外崩溃