Python Try except:通过示例进行解释

Python 中的 Try Except 结构:异常处理详解

在 Python 编程中,try...except 语句是一种强大的工具,用于优雅地处理程序运行中可能出现的异常情况,从而避免程序意外崩溃。 异常处理能够显著提高代码的健壮性和可靠性,降低程序出现故障的风险。 本文将深入探讨异常处理机制,分析其适用场景,并介绍如何主动引发异常。

什么是异常处理?

异常是程序执行过程中发生的特殊情况,例如错误或意外事件。 如果这些异常没有被妥善处理,程序就会终止并报错。 因此,异常处理是一种捕获并处理这些异常的机制,确保程序在遇到问题时能够继续运行,或者至少能够以一种可控的方式停止。

以下示例演示了异常的产生:

user_input = input("请输入一个数字:")
num = int(user_input)
print("您输入的数字乘以 2 的结果是:", num * 2)

这段代码初看似乎没有问题。 它接收用户输入,将其转换为整数,然后输出该整数的两倍。

如果用户输入 5,程序将顺利执行,输出结果。

然而,如果用户输入的是字符串 “hello”,而不是数字,程序就会崩溃。 因为字符串 “hello” 不能被转换为整数,这将导致一个异常,从而导致程序停止运行。

为什么会引发异常?为什么要处理它们?

在编写代码时,我们通常会将程序拆分成多个函数。 这些函数相互调用,执行不同的任务。

在上面的示例中,我们调用了 input 函数来获取用户输入,然后调用 int 函数将字符串转换为整数,最后调用 print 函数来输出结果。

当函数执行其操作时,可能会遇到它无法处理的错误。 在这种情况下,函数需要停止执行并报告错误。 为了做到这一点,它会引发一个异常。

调用函数的代码负责监听这些异常并采取适当的措施。 如果不这样做,程序就会在遇到错误时崩溃,就像我们在前面的例子中看到的那样。

因此,异常实际上是一种通信机制,允许被调用的函数向调用它的代码发送求救信号。 响应这个信号,采取适当的措施,就是异常处理的本质。

不同类型的异常

重要的是要了解,并非所有异常都是相同的。 不同类型的错误会引发不同类型的异常。 例如,尝试将数字除以零会引发 ZeroDivisionError。 尝试使用无效数据类型执行操作会引发 TypeError。 这里有异常类型的完整列表

如何处理异常

如前所述,异常是函数发出的求救信号。 我们的代码应该监听这些信号,并在收到信号时采取相应的行动。 为了正确处理异常,我们使用 Python 的 try...except 结构。 基本结构如下:

try:
    # 尝试执行的代码
except:
    # 如果发生异常,则执行此代码
finally:
    # 无论是否发生异常,都会执行此代码

如您所见,该结构由三个关键字组成:

try

try 关键字标记 try...except 结构的开始,它同时也标记了可能引发异常的代码块。 它指示 Python 解释器尝试运行该代码块中的代码。 如果抛出异常,程序会立即停止并跳转到执行 except 代码块中的代码。

except

except 关键字标记在执行 try 代码块时抛出异常时将要执行的代码块。 您可以为不同类型的异常定义多个 except 代码块,稍后我们将对此进行说明。

finally

finally 关键字是 try...except 结构中使用的第三个也是最后一个关键字。 它标记了无论是否发生异常都将执行的代码块。

一个示例

以下是一个示例,演示了上述关键字如何处理异常。 我们将之前的示例修改为如下所示:

try:
    user_input = input("请输入一个数字:")
    num = int(user_input)
    print("您输入的数字乘以 2 的结果是:", num * 2)
except:
    print("发生了一些错误")
finally:
    print("无论如何,这段代码都会被执行")

如果用户输入有效数字 5,您将看到以下结果:

如果输入 “hello”,您将看到以下结果:

因此,当在 try 代码块中执行代码时未引发异常时,计算机将跳转到 finally 代码块。 但是,当在 try 代码块中执行代码时引发异常时,计算机将跳转到 except 代码块,然后执行 finally 代码块。

您还可以处理特定类型的异常。 例如,如果您想以特定的方式处理 ValueErrorKeyboardInterrupt 异常,您可以像这样修改上面的代码:

try:
    user_input = input("请输入一个数字:")
    num = int(user_input)
    print("您输入的数字乘以 2 的结果是:", num * 2)
except ValueError:
    print("值不能转换为整数")
except KeyboardInterrupt:
    print("收到键盘中断")
except:
    print("捕获所有异常的块")
finally:
    print("无论如何,这段代码都会被执行")

在上面的代码中,我们有 3 个 except 代码块。 第一个 except 代码块仅捕获 ValueError 异常,而第二个块仅捕获 KeyboardInterrupt 异常。 最后一个 except 代码块没有要监听的关联异常类型。 因此,它捕获了前两个块未捕获的剩余异常。

运行上面的代码,你应该看到类似于这样的输出:

当发生异常时,您可以获取有关异常的更多信息。 您可以使用 as 关键字来访问异常对象。 其用法如下:

try:
    user_input = input("请输入一个数字:")
    num = int(user_input)
    print("您输入的数字乘以 2 的结果是:", num * 2)
except ValueError as e:
    print("ValueError:", e)
except KeyboardInterrupt as e:
    print("KeyboardInterrupt:", e)
except Exception as e:
    print("其他异常", e)

如何引发异常

到目前为止,我们一直在处理其他函数引发的异常。 但是,您也可以在代码中引发异常。 要引发异常,我们使用 raise 关键字。 我们还需要指定一个类来表示我们要引发的异常类型,以及一个与异常相关的、人类可读的消息。

在下面的示例中,我们使用 Exception 类引发一个通用异常。 然后,我们将消息传递给类的构造函数。

raise Exception('发生了一些错误')

如果您将上面的代码片段作为程序运行,您将获得类似如下的输出:

您还可以指定不同类型的异常。 例如,当值的数据类型错误时,您可以引发 TypeError 异常:

def double(x):
    if isinstance(x, int):
        return x * 2
    else:
        raise TypeError('x 应该是一个整数')

或者,如果指定的值超出可接受的范围,则可以引发 ValueError

def say_hello(name):
    if name == '':
        raise ValueError('值超出范围')
    else:
        print('你好', name)

您还可以通过继承 Exception 类来创建自己的异常类型。 这是一个例子:

class InvalidHTTPMethod(Exception):
    pass

在上面的例子中,我们创建了一个继承自 Exception 类的 InvalidHTTPMethod 类。 我们可以像以前一样使用它来引发异常:

raise InvalidHTTPMethod('必须是 GET 或 POST 方法')

异常处理的常见应用场景

异常处理在许多场景中都有应用。 前面的示例展示了它如何处理由用户输入引起的异常。 本节将介绍另外两种可以使用异常处理的情况。 它们包括处理网络请求失败和读取文件时出现的异常。

发出网络请求

在下面的示例中,我们向 Google 发出请求。 我们监听异常以处理它们。 这些异常是在 requests.exceptions 对象中定义的。

import requests

try:
    response = requests.get("https://google.com")

    # 检查响应状态码是否在 200-299 范围内(成功响应)
    if 200 <= response.status_code < 300:
        print("请求成功!")
    else:
        print(f"请求失败,状态码为:{response.status_code}")
except requests.exceptions.RequestException as e:
    print(f"RequestException 发生:{e}")
except requests.exceptions.ConnectionError as e:
    print(f"ConnectionError 发生:{e}")
except requests.exceptions.Timeout as e:
    print(f"Timeout 发生:{e}")
except requests.exceptions.TooManyRedirects as e:
    print(f"TooManyRedirects 发生:{e}")
except requests.exceptions.HTTPError as e:
    print(f"HTTPError 发生:{e}")
except Exception as e:
    print(f"发生意外错误:{e}")

从文件中读取数据

在最后一个示例中,我们从 hello.txt 文件读取数据。 我们还处理可能引发的常见异常,例如 FileNotFound 错误和 IOError

try:
    with open(file_path, 'r') as file:
        data = file.read()
        print("文件内容:")
        print(data)
except FileNotFoundError as e:
    print(f"FileNotFoundError 发生:{e}")
except IOError as e:
    print(f"IOError 发生:{e}")
except Exception as e:
    print(f"发生意外错误:{e}")

结论

本文探讨了异常是什么以及为什么会引发异常。 我们还认识到处理异常是为了提高代码的可靠性并防止崩溃。 最后,我们介绍了如何处理异常以及如何引发异常。

接下来,请查看常见的 Python 错误类型以及如何解决它们。