python基础(14)——异常 & 错误类型
一、异常 exception
1、什么是错误
错误是指由于逻辑或语法等导致一个程序无法正常执行的问题。
2、什么是异常
异常是程序出错时标识的一种状态
当异常发生时,程序不会再向下执行,而转去调用此函数的地方待处理此错误并恢复为正常状态
3、异常的作用:
用作信号,通知上层调用者有错误产生需要处理
4、简单理解为:错误是引起异常的原因,异常是当错误发生时的一种状态。
二、异常的四条语句:
try语句的两种法:
try-except语句
try-finally语句
执行必须要执行的语句(无论是正常还是异常状态)
raise 语句
抛出错误产生异常
assert 语句
当条件不满足时,抛出AssertionError类型的错误并进入异常状态
1、try-except语句
1、语法:
try:
可能触发异常的语法
except 错误类型1 [as 变量1]:
异常处理语句1
except 错误类型2 [as 变量2]:
异常处理语句2
except (错误类型3,错误类型4):
异常处理语句3
....
except:
异常处理语句other
else:
末发生异常语句
finally:
最终语句
2、作用:
偿式捕获异常(接收异常通知),将程序转为正常状态并继承执行。
3、语法说明:
as 子句是用于绑定错误对象的变量,可以省略
except 子句可以有一个或多个,但至少要有一个
else 子句最多只能有一个,也可以省略不写
finally 子句最多只能有一个,也可以省略不写
1 try: 2 n = int(input("请输入整数:")) 3 except int: # 错误,int类型不能当成错误类型用于try-except语句中 4 pass
1 def div_apple(n): 2 print("%d个苹果您想分给几个人?" % n) 3 s = input('请输入人数: ') 4 cnt = int(s) # <<- 可能触发ValueError错误进入异常 5 result = n / cnt # <<-- 可能触ZeroDivisionError错误 6 print("每个人分了", result, '个苹果') 7 8 try: 9 div_apple(10) 10 print("分苹果完成") 11 except ValueError: 12 print("在try的内部语句中发生了值错误,已处理并转为正常状态") 13 except ZeroDivisionError: 14 print('输入人数为零,分苹果失败!') 15 16 print("程序正常退出")
1 def div_apple(n): 2 print("%d个苹果您想分给几个人?" % n) 3 s = input('请输入人数: ') 4 cnt = int(s) # <<- 可能触发ValueError错误进入异常 5 result = n / cnt # <<-- 可能触ZeroDivisionError错误 6 print("每个人分了", result, '个苹果') 7 8 try: 9 div_apple(10) 10 print("分苹果完成") 11 except (ValueError, ZeroDivisionError): 12 print("分苹果失败,苹果不分了") 13 14 # except ValueError: 15 # print("分苹果失败,苹果不分了") 16 # except ZeroDivisionError: 17 # print("分苹果失败,苹果不分了") 18 19 print("程序正常退出")
1 def div_apple(n): 2 print("%d个苹果您想分给几个人?" % n) 3 s = input('请输入人数: ') 4 cnt = int(s) # <<- 可能触发ValueError错误进入异常 5 result = n / cnt # <<-- 可能触ZeroDivisionError错误 6 print("每个人分了", result, '个苹果') 7 8 try: 9 div_apple(10) 10 print("分苹果完成") 11 except ValueError: 12 print("在try的内部语句中发生了值错误,已处理并转为正常状态") 13 except: 14 print('收到除ValueError类型以外的错误通知') 15 16 print("程序正常退出")
1 # 此示例示意try-except语句中 as 变量的用法 2 def div_apple(n): 3 print("%d个苹果您想分给几个人?" % n) 4 s = input('请输入人数: ') 5 cnt = int(s) # <<- 可能触发ValueError错误进入异常 6 result = n / cnt # <<-- 可能触ZeroDivisionError错误 7 print("每个人分了", result, '个苹果') 8 9 try: 10 div_apple(10) 11 print("分苹果完成") 12 except ValueError as err: 13 print("错误值是: ", err) # err绑定错误对象 14 15 print("程序正常退出")
1 # 此示例示意try-except语句中else子句的用法 2 def div_apple(n): 3 print("%d个苹果您想分给几个人?" % n) 4 s = input('请输入人数: ') 5 cnt = int(s) # <<- 可能触发ValueError错误进入异常 6 result = n / cnt # <<-- 可能触ZeroDivisionError错误 7 print("每个人分了", result, '个苹果') 8 9 try: 10 div_apple(10) 11 print("分苹果完成") 12 except ValueError as err: 13 print("错误值是: ", err) # err绑定错误对象 14 else: # 只有在try没发错误发生时才会执行 15 print("在当前try语句内部,没有发生任何的异常,程序走正常流程") 16 17 print("程序正常退出")
1 # 此示例示意try-except语句中else子句的用法 2 def div_apple(n): 3 print("%d个苹果您想分给几个人?" % n) 4 s = input('请输入人数: ') 5 cnt = int(s) # <<- 可能触发ValueError错误进入异常 6 result = n / cnt # <<-- 可能触ZeroDivisionError错误 7 print("每个人分了", result, '个苹果') 8 9 try: 10 div_apple(10) 11 print("分苹果完成") 12 except ValueError: 13 print("错误值是: ") 14 else: 15 print("else子句被执行") 16 finally: 17 # finally 子句的语句无论是正常流程还是异常流程都会被执行 18 print('我这条语句一定会执行的') 19 20 print("程序正常退出")
练习:
写一个函数 get_score() 来获取学生输入的成绩 (0 ~ 100的整数)
输如果入出现异常,则让此函数返回0,否则返回用户输入的成绩
def get_score():
....
score = get_score()
print("学生的成绩是:", score)
注:
try-except语句也可以放在函数的内部使用
1 # 方法1,在调用的地方加入导常处理语句,然后进行处理 2 def get_score(): 3 n = int(input("请输入整数(0~100): ")) 4 if 0 <= n <= 100: 5 return n 6 else: 7 return 0 8 try: #在调用的地方加入导常处理语句,然后进行处理 9 score = get_score() 10 except ValueError: 11 score = 0 # 如果输入不合法,将成绩置零 12 13 print("学生的成绩是:", score)
1 # 方法2,在函数内部有可能抛出异常的函数加上try-except语句 2 def get_score(): 3 try: 4 n = int(input("请输入整数(0~100): ")) 5 except ValueError: 6 return 0 # 如果有异常发生,则直接返回0 7 if 0 <= n <= 100: 8 return n 9 else: 10 return 0 11 12 score = get_score() 13 print("学生的成绩是:", score)
2、try-finally语句
1、语法:
try:
可能触发异常的语句
finally:
最终语句
2、说明:
finally 子句不可以省略
一定不存在except子句
3、作用:
通常用try-finally语句来做触发异常时必须要处理的事情,无论异常是否发生,finally子句都会被执行
try-finally 语句不会改变程序的(正常/异常状态)
1 def fry_egg(): 2 print("打开天燃气...") 3 try: 4 count = int(input("请输入鸡蛋个数: ")) 5 print("完成煎鸡蛋,共煎了%d个鸡蛋!" % count) 6 finally: 7 print('关闭天燃气') 8 9 try: 10 fry_egg() 11 except: 12 print("程序出现过异常,已转为正常状态") 13 14 print("程序正常退出")
1 x = 100 2 y = 200 3 try: 4 save_x = x 5 save_y = y 6 try: 7 x = int(input("请输入x:")) 8 y = int(input("请输入y:")) 9 # 用x, y当前值来调有和打印,打印完毕后,x,y依旧恢复原有数据 10 print("x=", x, "y =", y) 11 finally: 12 x = save_x 13 y = save_y 14 except: 15 pass 16 17 print("原始数据 依旧为 x=", x, "y =", y)
3、try语句嵌套
try嵌套是指一个try语句嵌套在另一个try语句内使用
1 #此示例示意try语句嵌套,在内层的try语句如果已经把状态转为正常状态 2 #则外层的try语句将收不到错误通知 3 try: 4 try: 5 n = int(input("请输入整数:")) 6 except ValueError: 7 print("在内层try语句内出现值错误,已转为正常状态") 8 else: 9 print("内层try语句没有出现异常") 10 except: 11 print('外层的try语句接收到的异常通知.已处理并转为正常状态') 12 else: 13 print("外层try语句没有出现异常")
4、raise 语句:
1、作用:
触发一个错误,让程序进入异常状态
发送错误通知给调用者
2、语法:
raise 异常类型
或
raise 异常对象
或
raise # 重新触发上一次异常
1 raise 语句 2 def make_except(): 3 print("开始") 4 # raise ValueError # 故意发送一个错误通知 5 # e = ValueError("这是故意制作的一个错误!") 6 # raise e 7 raise ZeroDivisionError 8 9 print("结束") 10 11 try: 12 make_except() 13 except ValueError as err: 14 print("make_except 发出了ValueError类型的错误,已捕获") 15 # 错误的原因如何获得? 16 print("错误的值是:", err) 17 18 print("程序结束")
1 def make_except(): 2 print("开始_make_except") 3 raise ValueError("我的一个值错误!") 4 print("结束....") 5 6 def get_except(): 7 try: 8 make_except() 9 except ValueError as err: 10 print("错误的值是:", err) 11 raise # 重新触发刚收到的错误 等同于raise err 12 13 try: 14 get_except() 15 except ValueError as err: 16 print("get_except内部发生值错误!", err) 17 18 print("程序结束")
练习:
写一个函数 get_age() 用来获取一个人的年龄信息
此函数规定用户只能输入1~140之间的整数,如果用户输入其它的数则直接触发ValueError类型的错误来通知调用者
def get_age():
...
try:
age = get_age():
print("用户输入的年龄是: ", age)
except ValueError as err:
print("用户输入的不是1~140的整数,获取年龄失败!")
1 def get_age(): 2 a = int(input("请输入年龄(1~140): ")) 3 if 1 <= a <= 140: 4 return a 5 raise ValueError("值不在1~140之间") 6 7 try: 8 age = get_age() 9 print("用户输入的年龄是: ", age) 10 except ValueError as err: 11 print("用户输入的不是1~140的整数,获取年龄失败!")
5、assert 语句(断言语句)
1、语法:
assert 真值表达式, 错误数据(通常是字符串)
2、作用:
当真值表达式为False时,用错误数据创建一个AssertionError类型的错误raise出去,并进入异常状态
等同于:
if 真值表达式 == False:
raise AssertionError(错误数据)
1 # assert语句的用法 2 def get_score(): 3 s = int(input("请输入学生成绩(0~100):")) 4 assert 0 <= s <= 100, '成绩超出范围!!!' 5 # 等同于: 6 # if (0 <= s <= 100) == False: 7 # raise AssertionError('成绩超出范围!!!') 8 return s 9 10 try: 11 score = get_score() 12 print("学生成绩为:", score) 13 except ValueError: 14 print("用户输入数字不能转为整数...") 15 except AssertionError: 16 print("用户输入的整数不在0~100之间...")
三、为什么要用异常处理机制
在程序调用层数较深时,向主调函数传递错误信息需要层层return 返回比较麻烦,所以用异常处理机制
1 # 异常处理机制 2 def f1(): 3 print("开始盖房子打地基...") 4 # err = ValueError("打地基挖出古物,停止施工") 5 # return err 6 print("地基完成") 7 8 def f2(): 9 print("开始盖房子地面以上部分....") 10 err = ValueError("要建高压线...停止施工") 11 return err 12 print("地面以上部分完工") 13 14 def f3(): 15 '''第一承包商开始找人盖房子''' 16 r = f1() 17 if r is not None: 18 return r 19 r = f2() 20 if r is not None: 21 return r 22 23 def build_house(): 24 '''第一承包商开始找人盖房子''' 25 r = f3() 26 if r is not None: 27 return r 28 29 r = build_house() 30 if r is not None: 31 print("出错:", r)
1 # 异常处理机制 2 def f1(): 3 print("开始盖房子打地基...") 4 # err = ValueError("打地基挖出古物,停止施工") 5 # raise err 6 print("地基完成") 7 8 def f2(): 9 print("开始盖房子地面以上部分....") 10 err = ValueError("要建高压线...停止施工") 11 raise err 12 print("地面以上部分完工") 13 14 def f3(): 15 '''第一承包商开始找人盖房子''' 16 f1() 17 f2() 18 19 def build_house(): 20 '''第一承包商开始找人盖房子''' 21 f3() 22 23 try: 24 build_house() 25 except ValueError as err: 26 print("出错:", err)
练习:
1. 一个球从100米高空落下,每次落地后反弹高度是原高度的一半,再落下
写程序算出皮球在第10次落地后反弹高度是多高?
打印出共经过了多少米的路程
1 #共经过的路程 2 def lucheng(n): 3 s=100 4 suma = 0 5 for i in range(1,n+1): 6 x = s / 2 7 suma += s + x 8 s = x 9 return suma 10 #第10次落地后反弹高度 11 print(lucheng(10)) 12 13 def gao(n): 14 s=100 15 for i in range(1,n+1): 16 x = s / 2 17 s = x 18 print(s) 19 gao(10)
2. 分解质因数: 输入一个正整数,分解质因数:
如输入:
90
则打印:
'90=2*3*3*5'
(质因数是指小数最小能被原数整除的素数(不包含1))
1 def is_prime(x): 2 if x < 2: 3 return False 4 for i in range(2, x): 5 if x % i == 0: 6 return False 7 return True 8 9 L = [] # 此列表用存储素数(质因数) 10 n = int(input("请输入一个正整数: ")) 11 number = n # 保存原有的数 12 13 # 判断如果n不为1则找质因数 14 while n != 1: 15 for i in range(2, n + 1): 16 # 依次让n除以i,如果整数则i为质因数 17 if n % i == 0 and is_prime(i): 18 L.append(i) 19 n = int(n / i) 20 break # 查找当前一个质固数结束 21 22 print(L) 23 print(number, "=", '*'.join([str(x) for x in L]), 24 sep='')
3. 修改原学生信息管理程序,加入异常处理语句,让程序在任何情况下都能按逻辑正常执行
如: 输入成绩和年龄时,如果用户输入非法空符串也不会导致程序崩溃
1 def input_student(): 2 L = [] # 创建一个新的列表,用此列表准备保存学生信息 3 # 录入学生信息 4 while True: 5 n = input("请输入姓名: ") 6 if not n: 7 break 8 try: 9 a = int(input("请输入年龄: ")) 10 s = int(input('请输入成绩: ')) 11 except: 12 print("您输入的有误,请重新输入!") 13 continue 14 # 创建一个新的字典,把学生的信息存入字典中 15 d = {} # 每一次都重新创建一个新的字典 16 d['name'] = n 17 d['age'] = a 18 d['score'] = s 19 L.append(d) 20 return L
四、Python全部的错误类型
| 错误类型 | 说明 |
|---|---|
| ZeroDivisionError | 除(或取模)零 (所有数据类型) |
| ValueError | 传入无效的参数 |
| AssertionError | 断言语句失败 |
| StopIteration | 迭代器没有更多的值 |
| IndexError | 序列中没有此索引(index) |
| IndentationError | 缩进错误 |
| OSError | 输入/输出操作失败 |
| ImportError | 导入模块/对象失败 |
| NameError | 未声明/初始化对象 (没有属性) |
| AttributeError | 对象没有这个属性 |
| GeneratorExit | 生成器(generator)发生异常来通知退出 |
| TypeError | 对类型无效的操作 |
| KeyboardInterrupt | 用户中断执行(通常是输入^C) |
| OverflowError | 数值运算超出最大限制 |
| FloatingPointError | 浮点计算错误 |
| BaseException | 所有异常的基类 |
| SystemExit | 解释器请求退出 |
| Exception | 常规错误的基类 |
| StandardError | 所有的内建标准异常的基类 |
| ArithmeticError | 所有数值计算错误的基类 |
| EOFError | 没有内建输入,到达EOF 标记 |
| EnvironmentError | 操作系统错误的基类 |
| WindowsError | 系统调用失败 |
| LookupError | 无效数据查询的基类 |
| KeyError | 映射中没有这个键 |
| MemoryError | 内存溢出错误(对于Python 解释器不是致命的) |
| UnboundLocalError | 访问未初始化的本地变量 |
| ReferenceError | 弱引用(Weak reference)试图访问已经垃圾回收了的对象 |
| RuntimeError | 一般的运行时错误 |
| NotImplementedError | 尚未实现的方法 |
| SyntaxError Python | 语法错误 |
| TabError | Tab 和空格混用 |
| SystemError | 一般的解释器系统错误 |
| UnicodeError | Unicode 相关的错误 |
| UnicodeDecodeError | Unicode 解码时的错误 |
| UnicodeEncodeError | Unicode 编码时错误 |
| UnicodeTranslateError | Unicode 转换时错误 |
| 以下为警告类型 | |
| Warning | 警告的基类 |
| DeprecationWarning | 关于被弃用的特征的警告 |
| FutureWarning | 关于构造将来语义会有改变的警告 |
| OverflowWarning | 旧的关于自动提升为长整型(long)的警告 |
| PendingDeprecationWarning | 关于特性将会被废弃的警告 |
| RuntimeWarning | 可疑的运行时行为(runtime behavior)的警告 |
| SyntaxWarning | 可疑的语法的警告 |
| UserWarning | 用户代码生成的警告 |
| 详见:help(builtins) |
posted on 2018-10-12 17:34 破天荒的谎言、谈敷衍 阅读(520) 评论(0) 收藏 举报
浙公网安备 33010602011771号