- images
- results
- .gitignore
- 1.1概论.ipynb
- 1.2 环境配置.pdf
- 1.3数据类型.ipynb
- 1.4 人机交互.ipynb
- 1.5 对象与变量.ipynb
- 1.6 编码与命名规范.ipynb
- 2.1 数值类型.ipynb
- 2.2 数值类型转换.ipynb
- 2.3 数值元算.ipynb
- 2.4常用数学运算函数.ipynb
- 2.5 math 模块及其应用.ipynb
- 2.6.1 逻辑值测试.ipynb
- 2.6.2 成员运算.ipynb
- 2.6.3 比较运算.ipynb
- 2.6.4 布尔运算.ipynb
- 2.6.5 运算优先级.ipynb
- 2.ipynb
- 3.1 流程控制结构.ipynb
- 3.3.1 for 循环语句.ipynb
- 3.3.3 rang.ipynb
- 3.3.3 while 循环语句.ipynb
- 3.4 and 3.5 分支结构和条件.ipynb
- 3.6 and 3.7 .ipynb
- 3.9 异常处理.ipynb
- 4 函数和模块化编程.ipynb
- 4.1 函数的定义、调用与返回值.ipynb
- 4.2 函数的参数传递.ipynb
- 4.3 变量的作用域.ipynb
- 4.4 匿名函数.ipynb
- 4.5 递归.ipynb
- 4.6 内置函数.ipynb
- 4.7 模块化程序设计.ipynb
- 5.1 序列通用操作.ipynb
- 5.1.1 索引.ipynb
- 5.1.2 切片.ipynb
- 5.1.3 序列拼接与重复.ipynb
- 5.1.4 成员测试.ipynb
- 5.2.1 字符串的创建.ipynb
- 5.2.2 字符串常量.ipynb
- 5.2.4 字符串的遍历.ipynb
- 5.2.5 文件遍历.ipynb
- 5.2.6 字符串的处理方法.ipynb
- 5.2.7 字符串格式化.ipynb
- 5.2.8 转义字符.ipynb
- 5.3 random 模块及其应用.ipynb
- 6.1 元组.ipynb
- 6.2 列表.ipynb
- 6.2.1 列表的创建.ipynb
- 6.2.2 列表的更新.ipynb
- 6.2.3 列表的删除.ipynb
- 6.2.4 列表的排序.ipynb
- 6.2.5 列表赋值与复制.ipynb
- 6.2.6 列表推导式.ipynb
- 6.2.8 常用内置函数.ipynb
- 6.2.9 列表嵌套及其排序.ipynb
- 6.3 列表综合应用.ipynb
- 7.1.1 集合的创建.ipynb
- 7.1.2可变集合类型的操作.ipynb
- 7.1.3 成员关系.ipynb
- 7.1.4 集合关系.ipynb
- 7.1.5 集合运算.ipynb
- 7.2.1 字典创建.ipynb
- 7.2.2 获取字典值.ipynb
- 7.2.3 修改字典值.ipynb
- 7.2.4内置函数与方法.ipynb
- 7.2.5字典排序输出.ipynb
- 7.3 集合与字典的应用.ipynb
- 8 中 numpy 概述.ipynb
- 8 中panda 库.ipynb
- 8.1 文件的打开与关闭.ipynb
- 8.2 文件读写操作.ipynb
- 8.3 文件的应用.ipynb
- 8.4 numpy 文件操作.ipynb
- 8.4.2 and 3.ipynb
- 8.5.1 pandas文件读写.ipynb
- 8.5.2 and 3 and 4.ipynb
- 9.1 matplotlib 线性图.ipynb
- 9.1.5 数据文化绘图.ipynb
- 9.2 非线性图.ipynb
- 9.3 词云.ipynb
- _overview.md
- _readme.ipynb
- coding_here.ipynb
- dream.png
- score.txt
- score_total.csv
- 成绩分析综合.json
3.9 异常处理.ipynb @master — view markup · raw · history · blame
3.8 异常处理¶
3.8.1 异常¶
异常是在程序执行过程中发生的一个事件,该事件会影响程序的正常执行。
一般情况下,在Python无法正常处理程序时或者说程序运行时候发生错误而没有被处理时就会发生一个异常。
这些异常会被Python中的内建异常类捕捉, 异常的类型有很多,在前面的学习过程中,遇到过__SyntaxError、 NameError 、TypeError、 ValueError__等多个错误提示信息,这些都是异常。
# 除数为0时,触发除零异常
a = 8
b = 0
print(a / b)
# 对象名字拼写错误,变量名未定义异常
pi = 3.14 # 圆周率
diameter = 4 # 直径
area = pi * ((dimeter / 2) ** 2) # 计算圆的面积
当程序发生异常时需要捕获他并进行一些处理,使其__平稳结束__,否则程序会终止执行甚至直接崩溃。
本节主要学习异常的一些处理方法和利用异常进行程序设计。
在程序设计过程中,要尽可能考虑全面,__避免__类似异常的存在,同时,尽可能对可能产生的异常进行__处理__,使程序具有更好的健壮性和容错性,避免程序__崩溃__。
也可以利用异常处理的方法实现程序的不同的功能。
Python中有许多内置的异常,有一个内置异常的完整层次结构,每当解释器检测到某类错误时,就能触发相对应的异常。
在程序设计过程中,可以编写特定的代码,专门用于捕捉异常,如果捕捉到某类异常,程序就执行另外一段代码,执行为该异常定制的逻辑,使程序能够正确运行,这种处理方法就是异常处理。
3.8.2 try…except子句¶
在Python中,可以使用try、except、else和finally这几个关键词来组成一个包容性很好的程序,通过 __捕捉和处理异常__,加强程序的 __健壮性__。用__try__可以检测语句块中的错误,从而让__except__语句捕获异常信息并处理。
try…except语法如下:
try:
<语句块1> #需要检测异常的代码块
except <异常名称1>:
<语句块2> #如果在try部份引发了异常名称1时执行的语句块
[except <异常名称2>:
<语句块3>] #如果在try部份引发了异常名称2时执行的语句块
[else:
<语句块4>] #没有异常发生时执行的语句块
[finally:
<语句块5>]
except语句和finally语句都不是必须的,但是二者必须要有一个,否则就没有try的意义了。
except语句可以有多个,Python会按except语句的顺序依次匹配指定的异常。
a, b = map(int, input().split())
try:
import bun
except ZeroDivisionError:
print('除数为0,不能做除法运算')
实例4.14 四则运算¶
随机产生两个整数,输出其加、减、乘、__除__的结果,结果为浮点数时保留小数点后2位。
题目很简单,下面代码可以完成计算,但考虑到随机生成数字时,b的值可能会取到整数0,此时__除数为0__,会触发异常(小概率事件,需多次运行,但理论上一定会出现这个问题。)
import random
a = random.randint(0, 20) # 随机产生一个20以内的整数
b = random.randint(0, 3) # 随机产生一个3以内的整数
sign = random.choice('+-*/') # 随机产生一个运算符号
print(f"{a} + {b} = {a + b}")
print(f"{a} - {b} = {a - b}")
print(f"{a} * {b} = {a * b}")
print(f"{a} / {b} = {a / b:.2f}")
注意到0不能做除数,所以当第二个数字为0时,程序要能够对异常输入进行处理,使程序不至于因除零异常而崩溃。
可以将__可能会触发异常的语句__“print(f"{a} / {b} = {a / b:.2f}")”放到__try__的语句块中,一旦触发异常,程序将执行__except__下面的语句块中的语句。
import random
a = random.randint(0, 20) # 随机产生一个20以内的整数
b = random.randint(0, 3) # 随机产生一个3以内的整数
sign = random.choice('+-*/') # 随机产生一个运算符号
print(f"{a} + {b} = {a + b}")
print(f"{a} - {b} = {a - b}")
print(f"{a} * {b} = {a * b}")
try:
print(f"{a} / {b} = {a / b:.2f}")
except ZeroDivisionError:
print('除数为0,不能做除法运算')
此题中非常肯定的知道只有当产生的 “b”值为“0”时,才会陷入异常,这种__问题明确__的情况下,尽可能用__if…else__ 语句进行处理。
import random
a = random.randint(0, 20) # 随机产生一个20以内的整数
b = random.randint(0, 5) # 随机产生一个5以内的整数
sign = random.choice('+-*/') # 随机产生一个运算符号
print(f"{a} + {b} = {a + b}")
print(f"{a} - {b} = {a - b}")
print(f"{a} * {b} = {a * b}")
if b == 0:
print('除数为0,不能做除法运算')
else:
print(f"{a} / {b} = {a / b:.2f}")
Python允许在一个程序里同时对多类异常进行捕捉,触发哪个异常就执行哪个异常对应的语句。
表3.6列出了Python中常见的异常名称及其描述,可以参考Python文档查看所有异常类及其子类。
| 异常名称 | 描述 |
|---|---|
| Exception | 常规异常的基类,可以捕获任意异常 |
| Syntax__Error__ | 语法错误 |
| Name__Error__ | 未声明/未初始化的对象(没有属性) |
| System__Error__ | 一般的解释器系统错误 |
| Value__Error__ | 传入无效的参数,或传入一个调用者不期望的值,即使值的类型是正确的 |
| Indentation__Error__ | 缩进错误(代码没有正确对齐) |
| Import__Error__ | 导入模块/对象失败(路径问题或名称错误) |
| ModuleNotFound__Error__ | 模块不存在 |
| ZeroDivision__Error__ | 除(或取模)零 |
| Overflow__Error__ | 数字运算超出最大限制 |
| Attribute__Error__ | 对象没有这个属性 |
| Index__Error__ | 索引超出序列边界,如x只有10个元素,序号为0-9,程序中却试图访问x[10] |
| Key__Error__ | 映射中没有这个键(试图访问字典里不存在的键) |
| Type__Error__ | 对类型无效的操作 |
| Tab__Error__ | Tab和空格混用 |
| Runtime__Error__ | 一般的运行时错误 |
try:
import turtle # import tutle 时输出“模块名称有误”
size = eval(input())
print(size) # 参数写成sizee时会输出“变量未定义”
turtle.circle(size)
turtle.done() # done写成one时,会输出“属性不存在”
except ModuleNotFoundError: # 遇到不同类型的异常给出不同的错误提示
print('模块名称有误')
except NameError:
print('变量未定义')
except AttributeError:
print('属性不存在')
except SyntaxError:
print('存在语法错误')
Python内置了的“__Exception__”类可以捕捉到所有内置的、非系统退出的异常,以及所有用户定义的异常。当需要输出程序遇到的异常时,可以使用以下方法:
try:
import tutle # 修改为import tutle 后运行时输出No module named 'tutle'
size = eval(input())
print(size) # size写成sizee时输出name 'sizee' is not defined
turtle.circle(size)
# 写成circe时输出 module 'turtle' has no attribute 'circe'
turtle.done()
except Exception as e:
print(e)
3.8.3 else子句¶
没有触发异常时执行的语句
3.8.4 finally子句¶
如果try中的异常没有在“Exception”中被指出,那么系统将会抛出默认错误代码(Traceback),并且终止程序,接下来的所有代码都不会被执行。
但如果有__finally关键字__存在,则会在程序抛出默认错误代码之前,__执行finally中的语句__。
这个方法在某些必须要结束的操作中颇为有用,如__释放文件句柄__,或__释放内存空间__等。
s = ''' 静夜思
李白
床前明月光,
疑是地上霜。
举头望明月,
低头思故乡。
'''
try:
file = open('test.txt', 'w', encoding='utf-8') # 以“写”模式打开文件
file.write(s) # 写入s中的字符串
file.seek(0) # 文件指针回到文件开头
for line in file: # 遍历逐行读文件
print(line, end='') # 逐行输出文件内容
# file.close()如果放在此处,如果前面遇到异常,将无法关闭文件
except:
print('文件读写权限错误')
finally:
file.close() # finally中的语句无论是否触发异常都会被执行,可确保文件关闭
3.8.5 异常处理的应用¶
在一些特殊情况下,可以应用异常来实现一些特定的功能。例如正整数A+B的问题,利用其他语言实现可能需要近100行代码,而用Python结合异常处理来实现,仅需不到20行就可以实现。
实例 4.15 正整数A+B¶
题的目标很简单,就是求两个正整数A和B的和,其中A和B都大于0。稍微有点麻烦的是,输入并不保证是两个正整数。
输入在一行给出A和B,其间以空格分开。
问题是A和B不一定是满足要求的正整数,有时候可能是超出范围的数字、负数、带小数点的实数、甚至是一堆乱码。
我们把输入中出现的第1个空格认为是A和B的分隔。题目保证至少存在一个空格,并且B不是一个空字符串。
如果输入的确是两个正整数,则按格式“A + B = 和”输出。如果某个输入不合要求,则在相应位置输出“?”,显然此时和也是“?”。
a, b = input().split(' ', maxsplit=1) # 根据空格切分输入为列表,切分一次
try:
a = int(a) # 列表第一个元素转整型,转换类型不成功则触发异常
if a <= 0: # 如转换成功,说明是整数,再判定是否为负数
a = '?'
except ValueError:
a = '?' # 当异常被触发时,表明不是整数,用?代替
try:
b = int(b) # 列表第二个元素转整型,转换类型不成功则触发异常
if b <= 0: # 如转换成功,说明是整数,再判定是否为负数
b = '?'
except ValueError:
b = '?' # 当异常被触发时,表明不是整数,用?代替
if a == '?' or b == '?':
print(f'{a} + {b} = {"?"}')
else:
print(f'{a} + {b} = {a + b}')
虽然try...except可以捕捉和处理程序中的异常,但不能过于依赖这种方法。在程序设计过程中,首先应该尽可能排除语法错误与逻辑错误,防御性方式编码比捕捉异常方式更好,应尽量采取这种编程方式,提升性能并且使程序更健壮。
不要试图用try语句解决所有问题,这将会极大的降低程序的性能。只有在错误发生的条件无法预知的情况下,才使用try...except进行处理。
在程序设计过程中,一般情况下异常处理与程序主要的功能是没有关系的,过多的应用异常处理,会导致代码可读性变差。要尽量减少try/except语句块中的代码量,try语句块的体积越大, 期望之外的异常就越容易被触发,越容易隐藏真正的错误,从而带来严重后果。
使用finally子句来执行那些无论try语句块中有没有异常都应该被执行的代码,常用于终止处理程序,这对于清理资源常常很有用,例如关闭文件。