- 时长: 90 分钟
- 教学目标:
- 复习
try...except
语句的基本用法和作用。 - 深入理解如何捕获多个不同类型的错误,并分别进行处理。
- 学习在
except
块中如何获取并打印详细的错误信息。 - 掌握
finally
语句的用法:无论try
块中是否发生错误,finally
块中的代码都一定会执行。 - 理解
finally
在资源清理(如文件关闭、数据库连接释放)中的重要作用。 - 能够编写更健壮的代码,有效处理程序运行时可能发生的多种异常情况。
- 复习
课程内容
1. 复习与引入 (10 分钟)
- 复习: 快速回顾上一节综合项目中
try-except
的应用(例如处理用户输入无效、文件找不到等)。 - 提出问题: 老师提问:“我们之前用
try-except
让程序在遇到错误时不会崩溃,而是打印一个提示。但有时候,一个代码块可能会引发好几种不同的错误,比如用户输入非数字,或者除数为零。我们怎么针对不同的错误给出不同的提示呢?另外,不管程序有没有出错,总有一些收尾工作(比如关闭文件、保存数据)是必须做的,有没有办法保证这些代码一定会被执行?” - 引出新知识: 今天我们将学习如何更精确地捕获和处理不同类型的错误,以及一个非常重要的
finally
语句,它能确保某些代码无论如何都会被执行,这对于程序的稳定性至关重要。
2. 捕获多种类型的错误 (20 分钟)
- 回顾基本捕获:
try...except:
(捕获所有错误)或try...except 错误类型:
(捕获特定错误)。 - 捕获多个特定错误: 可以写多个
except
块,每个块捕获一种特定的错误类型。print("--- 捕获多种错误示例 ---") try: user_input = input("请输入一个数字(不要输入0):") num = int(user_input) # 可能引发 ValueError result = 100 / num # 可能引发 ZeroDivisionError my_list = [10, 20] print(my_list[5]) # 可能引发 IndexError print("计算结果:", result) except ValueError: print("错误:您输入的内容不是有效的整数!") except ZeroDivisionError: print("错误:除数不能为零!") except IndexError: print("错误:列表索引超出了范围!") # 也可以在最后放一个通用的 Exception 来捕获所有未被上面捕获的错误 except Exception as e: print(f"发生了一个未知错误: {e}") print("程序继续执行。")
- 将多种错误类型放在一个
except
中: 如果对多种错误的处理方式相同,可以将它们放在一个元组里,用一个except
块捕获。print("--- 捕获多种错误类型(合并处理)示例 ---") try: data = {"name": "Alice"} print(data["age"]) # KeyError # result = 10 / 0 # ZeroDivisionError except (KeyError, ZeroDivisionError) as e: # 同时捕获 KeyError 和 ZeroDivisionError print(f"发生了数据访问或数学计算错误: {e}") except ValueError as e: print(f"发生了值转换错误: {e}") except Exception as e: print(f"发生了其他未知的错误: {e}") print("程序继续执行。")
- 使用
as e
获取错误对象: 在except 错误类型 as 变量名:
中,变量名
会得到一个错误对象,里面包含了错误的详细信息,打印它会非常有帮助。try: name = "Bob" # 故意制造一个错误:尝试对字符串求平方根 (TypeError) print(math.sqrt(name)) except TypeError as err: # 将错误对象存入 err 变量 print(f"错误类型: {type(err)}") print(f"错误信息: {err}") # 打印错误信息
- 动手实践: 学生编写一个程序,尝试从一个字典中获取用户输入的键的值。用
try-except
捕获KeyError
(键不存在)和TypeError
(如果用户输入的键类型不对),并分别打印不同的提示信息。
3. 无论如何都要执行 – finally
语句 (25 分钟)
- 概念:
finally
块是try-except
结构的一部分。无论try
块中的代码是否发生错误,finally
块中的代码都一定会执行。 - 语法:
try: # 可能会出错的代码 print("尝试执行 try 块。") # result = 1 / 0 # 这里如果出错 print("try 块中的其他代码。") except ZeroDivisionError: # 如果 try 块出错,且是 ZeroDivisionError,就执行这里 print("进入 except 块处理错误。") finally: # 无论 try 块是否出错,也无论 except 块是否执行,这里都会执行 print("进入 finally 块,这是最后一定会执行的代码。") print("程序继续执行 after try-except-finally。")
finally
的作用场景 (重点!):finally
最常用于清理资源,确保一些重要的操作(比如文件关闭、网络连接断开、数据库连接释放)无论程序是否正常运行都能被执行。- 文件操作中的
finally
(旧式用法,与with
对比): 之前我们学了with open()
可以自动关闭文件,这很方便。但如果不用with
,手动打开文件时,finally
就非常重要了。# 示例:文件操作中 finally 的应用 (不推荐直接使用,但为了理解 finally 很有用) file_obj = None # 确保 file_obj 变量在 try 外部定义,否则 except 或 finally 访问不到 try: file_obj = open("my_test_file.txt", "r") # 假设文件存在,可能引发 FileNotFoundError content = file_obj.read() print("文件内容:", content) # 模拟一个其他错误,导致文件没有被及时关闭 # data = 1 / 0 except FileNotFoundError: print("错误:文件不存在!") except Exception as e: # 捕获其他所有错误 print(f"读取文件时发生其他错误: {e}") finally: # 无论上面是否出错,只要 file_obj 被成功赋值,就尝试关闭它 if file_obj: # 检查 file_obj 是否已经被成功打开 (不为 None) file_obj.close() print("文件已在 finally 块中关闭。") else: print("文件未成功打开,无需关闭。") print("程序结束。")
- 与
with open()
对比:with open()
语句内部其实就是利用了try-finally
的机制来实现文件的自动关闭,所以我们更推荐使用with open()
来操作文件。但finally
的概念在其他需要资源清理的场景中仍然非常重要。 - 动手实践: 学生编写一个程序,包含
try
,except
和finally
。在try
块中尝试制造一个错误(例如除零),观察finally
块是否执行。 然后移除错误,再次观察finally
块是否依然执行。
4. 课堂练习 (15 分钟)
让学生独立完成以下练习:
- 练习 1: 编写一个程序,让用户输入一个字符串和一个整数索引。尝试从字符串中获取对应索引的字符并打印。使用
try-except IndexError
捕获索引超出范围的错误,并使用try-except ValueError
捕获用户输入索引不是整数的错误。my_string = "Python编程" # TODO: 获取用户输入的索引 (字符串) # TODO: 使用 try 块转换索引为整数,并访问字符串字符 # TODO: 编写 except ValueError 处理非整数输入 # TODO: 编写 except IndexError 处理索引越界
- 练习 2: 编写一个程序,让用户输入两个数字。尝试进行除法运算并打印结果。要求:
- 如果用户输入非数字,打印“输入无效,请确保都是数字。”
- 如果除数为零,打印“除数不能为零。”
- 无论除法是否成功,最后都打印一句“计算尝试完毕。”(使用
finally
)。
- 练习 3: (选做) 编写一个函数
read_and_process_file(filename)
,接收文件名作为参数。- 在函数内部使用
try-except FileNotFoundError
捕获文件不存在的错误。 - 在
try
块中打开文件(可以使用with open()
更简洁),读取所有行。 - 尝试将每行内容转换为整数并求和(这里可能会有
ValueError
)。 - 使用另一个
except ValueError
块来捕获转换错误,并打印“文件中包含无效的数字行”。 - 无论文件是否成功处理,最后都打印一句“文件处理完成。”(使用
finally
)。
- 在函数内部使用
5. 总结与提问 (5 分钟)
- 回顾: 回顾本节课内容:捕获多种错误类型的方法(多个
except
块,或用元组合并),as e
获取错误信息,finally
语句的特点(无论是否出错都执行),以及finally
在资源清理中的重要作用。 - 提问:
- 一个
try
块后面可以跟几个except
块? except (ValueError, TypeError):
这种写法有什么好处?finally
块里的代码什么时候会执行?- 在文件操作中,
finally
或with open()
有什么共同的优点?
- 一个
- 答疑: 回答学生问题。
6. 布置课后作业 (5 分钟)
- 作业 1: 编写一个函数
get_user_age()
,循环让用户输入年龄,直到用户输入一个有效的正整数为止。在函数内部使用try-except ValueError
和while True
循环,并在成功获取年龄后return
年龄。如果年龄不是正数,也要提示错误。 - 作业 2: 编写一个程序,尝试打开一个名为
log.txt
的文件,以追加模式写入一条日志信息“程序启动时间:[当前时间]”(使用datetime
模块获取当前时间)。无论写入是否成功,最后都打印“日志写入尝试结束。”(使用finally
)。 - 作业 3: (选做) 编写一个简单的学生成绩查询系统(命令行版)。
- 创建一个学生成绩字典,例如
{"小明": 90, "小红": 85, "小刚": 78}
。 - 让用户循环输入学生姓名,如果学生姓名在字典中,打印分数;如果不在,提示“该学生不存在”。
- 使用
try-except
捕获KeyboardInterrupt
错误(当用户按Ctrl+C
退出程序时会发生),并在捕获到此错误时,打印“程序被中断,再见!”然后退出循环。
- 创建一个学生成绩字典,例如
- 本网站名称:系统驰云
- 本站永久网址:https://blog.xxyyo.com
- 本网站的内容均来源于网络,仅供大家学习与交流,如有侵权,请联系站长365919529@qq.com删除处理。
- 本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
- 本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
- 本站资源大多存储在云盘,如发现链接失效,请联系我们我们会第一时间更新。365919529@qq.com
评论(0)