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
test_except.py
 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("程序正常退出")
try_except1.py
 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("程序正常退出")
try_except2.py
 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("程序正常退出")
try_except3.py
 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("程序正常退出")
try_except4.py
 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("程序正常退出")
try_except_else.py
 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("程序正常退出")
try_except_else_finally.py

练习:
   写一个函数 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
 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

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("程序正常退出")
try_finally.py
 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)
try_finally_test.py

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语句没有出现异常")
try_embed.py

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("程序结束")
raise1.py
 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("程序结束")
raise2.py

练习:
   写一个函数 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的整数,获取年龄失败!")
练习.py

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之间...")
assert.py

三、为什么要用异常处理机制

    在程序调用层数较深时,向主调函数传递错误信息需要层层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)
exception1.py
 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)
exception2.py 

练习:

   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)
练习1.py

  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='')
练习2.py

  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
练习3.py

四、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)    收藏  举报

导航