简介
在这个实验中,你将学习如何使用不同的技术来检查 Python 中是否捕获到了异常。本实验聚焦于异常处理,这是编写健壮且可靠的 Python 代码的关键环节。
本实验将引导你理解如何使用 try...except
块来处理异常,从而优雅地处理像 ZeroDivisionError
这样的错误。你将学习如何在 except
块中设置一个标志,以表明已经捕获到了异常。最后,本实验将介绍使用上下文管理器进行更可控的异常处理的概念。
在这个实验中,你将学习如何使用不同的技术来检查 Python 中是否捕获到了异常。本实验聚焦于异常处理,这是编写健壮且可靠的 Python 代码的关键环节。
本实验将引导你理解如何使用 try...except
块来处理异常,从而优雅地处理像 ZeroDivisionError
这样的错误。你将学习如何在 except
块中设置一个标志,以表明已经捕获到了异常。最后,本实验将介绍使用上下文管理器进行更可控的异常处理的概念。
在这一步中,你将学习 Python 中的异常处理。异常处理是编写健壮且可靠代码的关键部分。它使你能够优雅地处理程序执行过程中可能出现的错误,防止程序崩溃,并提供更友好的用户体验。
让我们从一个简单的例子开始。假设你要对两个数字进行除法运算,但第二个数字可能为零。在 Python 中,除以零是未定义的操作,会引发 ZeroDivisionError
异常。
在 LabEx 环境中打开 VS Code 编辑器。
在 ~/project
目录下创建一个名为 division.py
的新文件。
touch ~/project/division.py
编辑 division.py
文件,并添加以下代码:
## division.py
numerator = 10
denominator = 0
result = numerator / denominator
print(result)
使用 python
命令运行脚本:
python ~/project/division.py
你会看到类似如下的错误信息:
Traceback (most recent call last):
File "/home/labex/project/division.py", line 4, in <module>
result = numerator / denominator
ZeroDivisionError: division by zero
此错误信息表明,由于我们试图除以零,引发了 ZeroDivisionError
异常。如果没有异常处理,程序会突然终止。
现在,让我们使用异常处理来优雅地处理这个错误。
修改 division.py
文件,加入 try...except
块:
## division.py
numerator = 10
denominator = 0
try:
result = numerator / denominator
print(result)
except ZeroDivisionError:
print("Error: Cannot divide by zero.")
在这段代码中,try
块包含了可能引发异常的代码。如果在 try
块中出现 ZeroDivisionError
异常,except
块中的代码将被执行。
再次运行脚本:
python ~/project/division.py
现在,程序不会崩溃,而是会输出:
Error: Cannot divide by zero.
这展示了异常处理的基本结构:
try
块包含可能引发异常的代码。except
块指定要捕获的异常类型,以及当该异常发生时要执行的代码。你还可以使用多个 except
块来捕获多种类型的异常:
## division.py
numerator = 10
denominator = "abc"
try:
result = numerator / int(denominator)
print(result)
except ZeroDivisionError:
print("Error: Cannot divide by zero.")
except ValueError:
print("Error: Invalid input. Please enter a number.")
在这个例子中,我们添加了一个 ValueError
异常处理程序。如果 denominator
无法转换为整数(例如,它是像 "abc" 这样的字符串),就会引发 ValueError
异常,相应的 except
块将被执行。
运行脚本:
python ~/project/division.py
输出:
Error: Invalid input. Please enter a number.
通过预测和处理潜在的错误,异常处理使你能够编写更健壮、更友好的程序。
except
块中设置标志在这一步中,你将学习如何在 except
块中使用标志,根据是否发生异常来控制程序的流程。当你需要根据 try
块的执行结果执行不同的操作时,这是一种很有用的技术。
基于上一个示例,假设你想计算一个数的倒数,但前提是除法运算成功。你可以使用一个标志来指示除法是否成功,然后相应地计算倒数。
在 LabEx 环境中打开 VS Code 编辑器。
修改 ~/project
目录下的 division.py
文件,加入一个标志:
## division.py
numerator = 10
denominator = 2
success = True ## 初始化标志为 True
try:
result = numerator / denominator
print("Result of division:", result)
except ZeroDivisionError:
print("Error: Cannot divide by zero.")
success = False ## 如果发生错误,将标志设置为 False
except ValueError:
print("Error: Invalid input. Please enter a number.")
success = False ## 如果发生错误,将标志设置为 False
else:
print("No exception occurred.")
if success:
try:
reciprocal = 1 / result
print("Reciprocal:", reciprocal)
except ZeroDivisionError:
print("Cannot calculate reciprocal of zero.")
else:
print("Reciprocal calculation skipped due to error.")
在这段代码中:
try
块之前将一个名为 success
的标志初始化为 True
。ZeroDivisionError
或 ValueError
异常,我们会在相应的 except
块中将 success
标志设置为 False
。try...except
块之后,我们检查 success
标志的值。如果它仍然为 True
,则表示没有发生异常,我们可以安全地计算倒数。否则,我们跳过倒数的计算。else
块,如果 try
块中没有发生异常,该块将被执行。使用有效的分母运行脚本:
python ~/project/division.py
输出:
Result of division: 5.0
No exception occurred.
Reciprocal: 0.2
现在,将 denominator
改为 0
,然后再次运行脚本:
## division.py
numerator = 10
denominator = 0 ## 将分母改为 0
success = True
try:
result = numerator / denominator
print("Result of division:", result)
except ZeroDivisionError:
print("Error: Cannot divide by zero.")
success = False
except ValueError:
print("Error: Invalid input. Please enter a number.")
success = False
else:
print("No exception occurred.")
if success:
try:
reciprocal = 1 / result
print("Reciprocal:", reciprocal)
except ZeroDivisionError:
print("Cannot calculate reciprocal of zero.")
else:
print("Reciprocal calculation skipped due to error.")
运行脚本:
python ~/project/division.py
输出:
Error: Cannot divide by zero.
Reciprocal calculation skipped due to error.
这展示了你如何在 except
块中使用标志来控制程序的流程,并根据是否发生异常执行不同的操作。
在这一步中,你将学习如何在 Python 中使用上下文管理器来简化异常处理,并确保即使发生异常,资源也能得到妥善管理。上下文管理器在处理文件、网络连接和其他需要显式关闭或释放的资源时特别有用。
上下文管理器是定义了 __enter__
和 __exit__
方法的对象。with
语句用于在上下文管理器的上下文中执行一段代码。当进入 with
块时,会调用 __enter__
方法;当退出 with
块时,无论是否发生异常,都会调用 __exit__
方法。
让我们从一个使用上下文管理器读取文件的简单示例开始。
在 LabEx 环境中打开 VS Code 编辑器。
在 ~/project
目录下创建一个名为 file_handling.py
的新文件。
touch ~/project/file_handling.py
编辑 file_handling.py
文件,并添加以下代码:
## file_handling.py
filename = "my_file.txt"
try:
with open(filename, "w") as f:
f.write("Hello, LabEx!\n")
f.write("This is a test file.\n")
except IOError as e:
print(f"An I/O error occurred: {e}")
try:
with open(filename, "r") as f:
content = f.read()
print("File content:")
print(content)
except FileNotFoundError:
print(f"The file '{filename}' was not found.")
except IOError as e:
print(f"An I/O error occurred: {e}")
在这段代码中:
with open(filename, "w") as f:
语句以写入模式 ("w"
) 打开文件 my_file.txt
。open()
函数返回一个文件对象,并将其赋值给变量 f
。with
语句确保即使发生异常,在退出代码块时文件也会自动关闭。f.write()
方法向文件写入两行文本。with open(filename, "r") as f:
语句以读取模式 ("r"
) 打开同一个文件。f.read()
方法读取文件的全部内容,并将其打印到控制台。try...except
块中,以处理可能出现的 FileNotFoundError
和 IOError
异常。运行脚本:
python ~/project/file_handling.py
输出:
File content:
Hello, LabEx!
This is a test file.
如果文件 my_file.txt
不存在,脚本将创建该文件并写入指定的内容。如果文件已经存在,其内容将被覆盖。无论哪种情况,with
语句都能确保文件被正确关闭。
让我们考虑另一个在文件处理过程中可能发生异常的示例:
## file_handling.py
filename = "my_file.txt"
try:
with open(filename, "r") as f:
for line in f:
## Simulate an error during processing
if "test" in line:
raise ValueError("Simulated error during processing")
print("Line:", line.strip())
except FileNotFoundError:
print(f"The file '{filename}' was not found.")
except ValueError as e:
print(f"A value error occurred: {e}")
except IOError as e:
print(f"An I/O error occurred: {e}")
在这个示例中,如果某一行包含单词 "test",我们通过抛出 ValueError
来模拟一个错误。即使发生此错误,with
语句也能确保文件被正确关闭。
运行脚本:
python ~/project/file_handling.py
输出:
Line: Hello, LabEx!
A value error occurred: Simulated error during processing
上下文管理器为 Python 中的资源管理和异常处理提供了一种简洁可靠的方式。它们确保即使发生错误,资源也能得到正确释放,使你的代码更健壮、更易于维护。
在本次实验中,你首先学习了 Python 中的异常处理,这是编写健壮代码的一项关键技术。你从一个简单的除法示例开始,当除以零时会引发 ZeroDivisionError
,导致程序终止。然后,你实现了一个 try...except
块来优雅地处理 ZeroDivisionError
,防止程序崩溃,并输出一条有信息价值的错误消息。