如何检查 Python 中是否捕获到异常

PythonPythonBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

在这个实验中,你将学习如何使用不同的技术来检查 Python 中是否捕获到了异常。本实验聚焦于异常处理,这是编写健壮且可靠的 Python 代码的关键环节。

本实验将引导你理解如何使用 try...except 块来处理异常,从而优雅地处理像 ZeroDivisionError 这样的错误。你将学习如何在 except 块中设置一个标志,以表明已经捕获到了异常。最后,本实验将介绍使用上下文管理器进行更可控的异常处理的概念。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL python(("Python")) -.-> python/ControlFlowGroup(["Control Flow"]) python(("Python")) -.-> python/ErrorandExceptionHandlingGroup(["Error and Exception Handling"]) python(("Python")) -.-> python/FileHandlingGroup(["File Handling"]) python(("Python")) -.-> python/AdvancedTopicsGroup(["Advanced Topics"]) python/ControlFlowGroup -.-> python/conditional_statements("Conditional Statements") python/ErrorandExceptionHandlingGroup -.-> python/catching_exceptions("Catching Exceptions") python/ErrorandExceptionHandlingGroup -.-> python/raising_exceptions("Raising Exceptions") python/FileHandlingGroup -.-> python/file_opening_closing("Opening and Closing Files") python/FileHandlingGroup -.-> python/file_operations("File Operations") python/AdvancedTopicsGroup -.-> python/context_managers("Context Managers") subgraph Lab Skills python/conditional_statements -.-> lab-559610{{"如何检查 Python 中是否捕获到异常"}} python/catching_exceptions -.-> lab-559610{{"如何检查 Python 中是否捕获到异常"}} python/raising_exceptions -.-> lab-559610{{"如何检查 Python 中是否捕获到异常"}} python/file_opening_closing -.-> lab-559610{{"如何检查 Python 中是否捕获到异常"}} python/file_operations -.-> lab-559610{{"如何检查 Python 中是否捕获到异常"}} python/context_managers -.-> lab-559610{{"如何检查 Python 中是否捕获到异常"}} end

学习异常处理流程

在这一步中,你将学习 Python 中的异常处理。异常处理是编写健壮且可靠代码的关键部分。它使你能够优雅地处理程序执行过程中可能出现的错误,防止程序崩溃,并提供更友好的用户体验。

让我们从一个简单的例子开始。假设你要对两个数字进行除法运算,但第二个数字可能为零。在 Python 中,除以零是未定义的操作,会引发 ZeroDivisionError 异常。

  1. 在 LabEx 环境中打开 VS Code 编辑器。

  2. ~/project 目录下创建一个名为 division.py 的新文件。

    touch ~/project/division.py
  3. 编辑 division.py 文件,并添加以下代码:

    ## division.py
    numerator = 10
    denominator = 0
    
    result = numerator / denominator
    
    print(result)
  4. 使用 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 异常。如果没有异常处理,程序会突然终止。

现在,让我们使用异常处理来优雅地处理这个错误。

  1. 修改 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 块中的代码将被执行。

  2. 再次运行脚本:

    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 块的执行结果执行不同的操作时,这是一种很有用的技术。

基于上一个示例,假设你想计算一个数的倒数,但前提是除法运算成功。你可以使用一个标志来指示除法是否成功,然后相应地计算倒数。

  1. 在 LabEx 环境中打开 VS Code 编辑器。

  2. 修改 ~/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
    • 如果发生 ZeroDivisionErrorValueError 异常,我们会在相应的 except 块中将 success 标志设置为 False
    • try...except 块之后,我们检查 success 标志的值。如果它仍然为 True,则表示没有发生异常,我们可以安全地计算倒数。否则,我们跳过倒数的计算。
    • 我们还添加了一个 else 块,如果 try 块中没有发生异常,该块将被执行。
  3. 使用有效的分母运行脚本:

    python ~/project/division.py

    输出:

    Result of division: 5.0
    No exception occurred.
    Reciprocal: 0.2
  4. 现在,将 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__ 方法。

让我们从一个使用上下文管理器读取文件的简单示例开始。

  1. 在 LabEx 环境中打开 VS Code 编辑器。

  2. ~/project 目录下创建一个名为 file_handling.py 的新文件。

    touch ~/project/file_handling.py
  3. 编辑 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.txtopen() 函数返回一个文件对象,并将其赋值给变量 f
    • with 语句确保即使发生异常,在退出代码块时文件也会自动关闭。
    • 我们使用 f.write() 方法向文件写入两行文本。
    • 然后,我们使用 with open(filename, "r") as f: 语句以读取模式 ("r") 打开同一个文件。
    • 我们使用 f.read() 方法读取文件的全部内容,并将其打印到控制台。
    • 我们将文件操作封装在 try...except 块中,以处理可能出现的 FileNotFoundErrorIOError 异常。
  4. 运行脚本:

    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,防止程序崩溃,并输出一条有信息价值的错误消息。