跳转至

Python异常处理

约 737 个字 91 行代码 预计阅读时间 4 分钟

介绍

Python中有下面几种常见的异常

报错类型 描述
AssertionError assert断言条件为假的时候抛出的异常
AttributeError 当访问的对象属性不存在的时候抛出的异常
IndexError 超出对象索引的范围时抛出的异常
KeyError 在字典中查找一个不存在的key抛出的异常
NameError 访问一个不存在的变量时抛出的异常
OSError 操作系统产生的异常
SyntaxError 语法错误时会抛出此异常
TypeError 类型错误,通常是不同类型之间的操作会出现此异常
ZeroDivisionError 进行数学运算时除数为0时会出现此异常

Python中的异常处理方式

在Python中使用try-except语句,与其他编程语言类似,try的代码块包裹可能出现异常的代码,except后即为异常,如果不写指定异常,则默认捕获所有类型的异常

例如下面的代码:

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
try:
    num = int(input("请输入一个整数:"))
    result = 10 / num
    print(f"结果是:{result}")
except ZeroDivisionError:
    # 捕获除数为0的异常
    print("除数不能为0!")
except ValueError:
    # 捕获输入不是整数的异常
    print("请输入一个有效的整数!")
except:
    # 捕获其他异常
    print("未知错误!")

如果需要在捕获异常后打印出原始异常的报错,可以添加as将对应的异常修饰给一个变量,例如下面的代码:

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
try:
    num = int(input("请输入一个整数:"))
    result = 10 / num
    print(f"结果是:{result}")
except ZeroDivisionError as e:
    print(f"除数不能为0!原始错误信息:{e}")
except ValueError as e:
    print(f"请输入一个有效的整数!原始错误信息:{e}")
except Exception as e:
    print(f"发生了未知错误:{e}")

elsefinally

Python中的异常处理语句中,elsefinally 块为程序提供了更细粒度的控制,可以在异常处理过程中执行特定的代码。

else

用途:当 try 块中没有发生任何异常时执行 else 块的代码

特点:如果在 try 块中捕获到了异常,else 块将被跳过

示例

Python
1
2
3
4
5
6
7
8
9
try:
    num = int(input("请输入一个整数:"))
    result = 10 / num
except ZeroDivisionError as e:
    print(f"除数不能为0!原始错误信息:{e}")
except ValueError as e:
    print(f"请输入一个有效的整数!原始错误信息:{e}")
else:
    print(f"计算结果是:{result}")

finally

用途:无论是否发生异常,finally 块中的代码都会被执行

特点:常用于释放资源、关闭文件或进行清理工作

示例

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
try:
    num = int(input("请输入一个整数:"))
    result = 10 / num
    print(f"计算结果是:{result}")
except ZeroDivisionError as e:
    print(f"除数不能为0!原始错误信息:{e}")
except ValueError as e:
    print(f"请输入一个有效的整数!原始错误信息:{e}")
finally:
    print("程序执行完毕,无论是否发生异常,这里都会被执行。")

raise抛出异常

raise 语句用于在程序执行过程中主动抛出异常,以便中断正常的流程并进入异常处理机制。通过 raise可以做到下面的两件事情:

  • 引发内置异常,以提示特定的错误类型。
  • 创建并引发自定义异常,以提供更详细的错误信息。

引发内置异常

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
def divide(a, b):
    if b == 0:
        raise ZeroDivisionError("除数不能为0")
    return a / b

try:
    result = divide(10, 0)
except ZeroDivisionError as e:
    print(f"发生错误:{e}")

输出结果
发生错误除数不能为0

在上述示例中,divide 函数中当检测到除数为零时,使用 raise 抛出 ZeroDivisionError 异常,传递了自定义的错误信息。调用者使用 try-except 块捕获并处理该异常。

也可以定义自己的异常类并在出现异常的位置抛出该自定义异常,以便更精确地描述错误情况。自定义异常需要继承自 Exception

定义自定义异常:

Python
1
2
3
class NegativeNumberError(Exception):
    """自定义异常:负数错误"""
    pass

使用自定义异常:

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
def sqrt(x):
    if x < 0:
        raise NegativeNumberError("不能对负数求平方根")
    return x ** 0.5

try:
    result = sqrt(-9)
except NegativeNumberError as e:
    print(f"发生错误:{e}")

输出结果
发生错误不能对负数求平方根

重新引发异常

在异常处理过程中,可能需要在捕获异常后重新引发,以便上层代码进一步处理。

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
def process_data():
    try:
        # 可能引发异常的代码
        data = int("abc")
    except ValueError as e:
        print(f"处理数据时发生错误:{e}")
        raise  # 重新引发异常

try:
    process_data()
except Exception as e:
    print(f"主程序捕获到异常:{e}")

输出结果

处理数据时发生错误invalid literal for int() with base 10: 'abc'
主程序捕获到异常invalid literal for int() with base 10: 'abc'

使用 raise 不带参数

except 块中使用不带参数的 raise,可以重新引发当前捕获的异常:

Python
1
2
3
4
5
try:
    num = int("xyz")
except ValueError:
    print("捕获到 ValueError,重新引发异常")
    raise

这将重新引发之前捕获的 ValueError