Python 异常处理!
嗨,你好啊,我是猿java
这篇文章,我们将通过适当的示例讨论如何使用try、except和finally语句来处理Python中的异常。
Python中的错误可以分为两种类型,即语法错误和异常。错误是由于程序中的问题而导致程序停止执行的情况。而异常是在出现某些内部事件时引发的,从而改变程序的正常流程。
Python中的异常类型
在 Python中,有几种内置的异常,当程序执行过程中出现错误时会抛出这些异常,以下是 Python中最常见的一些异常类型:
- SyntaxError: 当解释器在代码中遇到语法错误时引发此异常,例如拼写错误的关键字、缺少的冒号或不平衡的括号。
- TypeError: 当一个操作或函数应用于错误类型的对象时引发此异常,例如将字符串加到整数上。
- NameError: 当变量或函数名称在当前作用域中未找到时引发此异常。
- IndexError: 当列表、元组或其他序列类型的索引超出范围时引发此异常。
- KeyError: 当在字典中找不到键时引发此异常。
- ValueError: 当函数或方法调用时提供了无效的参数或输入时引发此异常,例如尝试将字符串转换为整数而该字符串不表示有效整数。
- AttributeError: 当对象上找不到属性或方法时引发此异常,例如试图访问类实例的不存在的属性。
- IOError: 当输入/输出操作失败时引发此异常,例如读取或写入文件时发生输入/输出错误。
- ZeroDivisionError: 当尝试将数字除以零时引发此异常。
- ImportError: 当导入语句未能找到或加载模块时引发此异常。
这些只是许多可能在Python中发生的异常类型中的一部分。通过使用try-except块或其他错误处理技术,适当地处理异常是很重要的,这样可以优雅地处理错误并防止程序崩溃。
语法错误和异常的区别
语法错误: 顾名思义,这种错误是由代码中的语法错误引起的,它会导致程序的终止。
以下示例代码中存在语法错误。‘if’语句应紧跟一个冒号(:),并且‘print’语句应缩进到‘if’块内部。
1 | amount = 10000 |
异常: 异常是在程序语法正确的情况下引发的错误,但代码结果却发生错误。此错误不会停止程序的执行,但会改变程序的正常流程。
如下示例代码中,我们将‘marks’除以零,因此会发生称为‘ZeroDivisionError’的错误。‘ZeroDivisionError’ 发生在尝试将任何数字除以0时。
1 | marks = 10000 |
在上述示例中,由于我们试图将一个数字除以0,因此引发了ZeroDivisionError异常。
注意: Exception是Python中所有异常的基类。
- TypeError: 当一个操作或函数应用于错误类型的对象时引发此异常。
以下示例试图将两种不同数据类型相加,引发了‘TypeError’异常:
1 | x = 5 |
输出:
1 | Traceback (most recent call last): |
使用try-except块解决它:
代码尝试将一个整数(‘x’)和一个字符串(‘y’)相加,这是无效的操作,并会引发‘TypeError’异常。代码使用‘try’和‘except’块捕获此异常并打印错误消息。
1 | x = 5 |
输出:
1 | 错误: 不能将int和str相加 |
Try和Except语句——捕获异常
Try和except语句用于捕获和处理Python中的异常。可能引发异常的语句被放在try块中,而处理异常的语句则写在except块中。
示例:这里我们试图访问数组中越界的元素并处理对应的异常。
1 | a = [1, 2, 3] |
输出:
1 | 第二个元素 = 2 |
在上述示例中,可能导致错误的语句放在try语句中(我们的案例中是第二个print语句)。第二个打印语句尝试访问列表中的第四个元素,而该元素不存在,因而抛出异常。该异常被except语句捕获。
捕获特定异常
try语句可以有多个except条款,以指定不同异常的处理程序。请注意,最多只有一个处理程序会被执行。例如,我们可以在上述代码中添加IndexError。添加特定异常的一般语法是:
1 | try: |
示例:捕获Python中的特定异常
代码定义了一个名为‘fun(a)’的函数,该函数根据输入a计算b。如果a小于4,它会尝试除以零,从而导致‘ZeroDivisionError’。代码在try-except块中调用fun(3)和fun(5)。它处理fun(3)时的ZeroDivisionError,并打印“ZeroDivisionError发生并已处理”。由于代码中没有‘NameError’异常,因此‘NameError’块不被执行。
1 | def fun(a): |
输出:
1 | ZeroDivisionError发生并已处理 |
如果注释掉fun(3)行,输出将是:
1 | NameError发生并已处理 |
上述输出是因为一旦 Python尝试访问 b的值,就会发生NameError异常。
带有 Else子句的Try语句
在Python中,你还可以在try-except块中使用else子句,该子句必须位于所有except块之后。代码仅在try块不抛出异常时才进入else块。
带有Else子句的Try语句
代码定义了一个名为AbyB(a, b)的函数,该函数计算c为((a+b) / (a-b))并处理潜在的ZeroDivisionError。如果没有发生除以零错误,它会打印结果。调用AbyB(2.0, 3.0)计算并打印-5.0,而调用AbyB(3.0, 3.0)尝试除以零,结果导致ZeroDivisionError,该异常被捕获并打印“a/b结果为0”。
1 | def AbyB(a , b): |
输出:
1 | -5.0 |
Finally关键字在Python中的用法
Python提供了finally关键字,它始终在try和except块之后执行。无论是try块正常终止还是try块由于某些异常终止,最终块总是执行。最终块中的代码总是被执行。
语法:
1 | try: |
以下示例代码尝试执行除以零的整数除法,导致ZeroDivisionError。它捕获该异常并打印“不能除以零”。无论是否发生异常,最终块会执行并打印“这总是执行”。
1 | try: |
输出:
1 | 不能除以零 |
抛出异常
raise语句允许程序员强制发生特定异常。raise的唯一参数说明要引发的异常。这个参数必须是异常实例或异常类(从Exception派生的类)。
这段代码在try块中使用raise语句,带有消息“Hi there”主动引发一个NameError异常。然后,它捕获NameError异常,打印“发生异常”,并使用raise重新抛出相同的异常。这展示了如何在Python中引发和处理异常,允许自定义的错误消息和进一步的异常传播。
1 | try: |
上述代码的输出将只会打印一行“发生异常”,但由于最后一行中的raise语句,最后也会发生运行时错误。所以在你的命令行上,输出将是:
1 | Traceback (most recent call last): |
异常处理的优点:
- 提高程序的可靠性: 通过正确处理异常,可以防止程序因意外错误或输入而崩溃或产生错误结果。
- 简化错误处理: 异常处理允许将错误处理代码与主程序逻辑分离,使程序更易读和维护。
- 代码更简洁: 使用异常处理,可以避免使用复杂的条件语句来检查错误,从而使代码更简洁、更易读。
- 调试更容易: 当引发异常时,Python解释器会打印出异常发生的确切位置的追踪信息,使得调试代码更加容易。
异常处理的缺点:
- 性能开销: 异常处理可能比使用条件语句检查错误要慢,因为解释器需要执行额外的工作来捕获和处理异常。
- 增加代码复杂性: 异常处理可能使你的代码更复杂,特别是当你需要处理多种类型的异常或实现复杂的错误处理逻辑时。
- 可能的安全风险: 处理不当的异常可能会暴露敏感信息或在代码中创建安全漏洞,因此务必要仔细处理异常,避免暴露过多有关程序的信息。
学习交流
如果你觉得文章有帮助,请帮忙转发给更多的好友,或关注公众号:猿java,持续输出硬核文章。