Skip to content

Python 异常处理 ​

如果程序报错,不会结束程序,而是执行 except 里面的的代码

捕获常规异常 ​

python
try:
    open("d:/Python/dataType/haha0.txt","r",encoding="utf-8")
    print("result:")
except:
    open("d:/Python/dataType/haha0.txt","a",encoding="utf-8")
    print("except...")
try:
    open("d:/Python/dataType/haha0.txt","r",encoding="utf-8")
    print("result:")
except:
    open("d:/Python/dataType/haha0.txt","a",encoding="utf-8")
    print("except...")

捕获特定异常 ​

  • 如果尝试执行的代码的异常类型和要捕获的异常类型不一致,则无法捕获异常。
python
try:
    可能发生错误的代码
except 待捕获异常名 as 别名:
    如果出现异常执行的代码
try:
    可能发生错误的代码
except 待捕获异常名 as 别名:
    如果出现异常执行的代码

捕获多个异常 ​

  • 格式一:当待捕获异常名为Exception可以捕获所有类型异常,作用与常规异常一样一致

    python
    try:
        f = open("C:/code/study.txt", "r")
    except Exception as e:
        print('文件不存在')
    try:
        f = open("C:/code/study.txt", "r")
    except Exception as e:
        print('文件不存在')
  • 格式二:把要捕获的异常类型的名字,放到 except 后,并使用元组的方式进行书写。

    python
    try:
        可能发生错误的代码
    except (异常名1,异常名2) as 别名:
        如果出现异常执行的代码
    try:
        可能发生错误的代码
    except (异常名1,异常名2) as 别名:
        如果出现异常执行的代码

其他用法 ​

打印异常信息 ​
  • 异常描述信息存贮在别名中,可以通过打印别名获取

  • 使用示例:

    python
    try:
        print(num) # 未定义,报错
    except (NameError, ZeroDivisionError) as e:
        print(e) # 打印 name 'num' is not defined
    try:
        print(num) # 未定义,报错
    except (NameError, ZeroDivisionError) as e:
        print(e) # 打印 name 'num' is not defined
异常 else ​
  • else 表示的是如果没有异常要执行的代码。

  • 使用示例:

    python
    try:
        print(num) # 未定义,报错
    except (NameError, ZeroDivisionError) as e:
        print(e) # 打印 name 'num' is not defined
    else:
        print("无异常") # 有异常,不执行  //无异常执行
    try:
        print(num) # 未定义,报错
    except (NameError, ZeroDivisionError) as e:
        print(e) # 打印 name 'num' is not defined
    else:
        print("无异常") # 有异常,不执行  //无异常执行
异常 finally ​
  • finally 表示的是无论是否异常都要执行的代码

  • 使用示例:

    • 果 open 文件却一直未 close 且程序未中止,将一直占用文件无法操作

    • 如果打开文件后发生异常,未 close 也将导致一直占用,因此可选择在 finally 中 close

      python
      global f
      try:
          f = open("C:/code/aaa.txt", "r")
      except Exception as e:
          print(e)
      finally:
          f.close() # 一定会执行close操作
      global f
      try:
          f = open("C:/code/aaa.txt", "r")
      except Exception as e:
          print(e)
      finally:
          f.close() # 一定会执行close操作

Python 3.11+:ExceptionGroup 与 except* ​

python
# ExceptionGroup 可以同时抛出和捕获多个异常

# 抛出异常组
def validate_user(data: dict) -> None:
    errors = []
    if "name" not in data:
        errors.append(ValueError("缺少 name"))
    if "age" not in data:
        errors.append(ValueError("缺少 age"))
    if "email" in data and "@" not in data["email"]:
        errors.append(TypeError("email 格式错误"))
    if errors:
        raise ExceptionGroup("用户数据校验失败", errors)

# 使用 except* 分别处理不同类型的异常
try:
    validate_user({"name": "Alice"})
except* ValueError as e:
    print(f"值错误: {e.exceptions}")
except* TypeError as e:
    print(f"类型错误: {e.exceptions}")

# ExceptionGroup 支持嵌套
try:
    raise ExceptionGroup("外层错误", [
        ValueError("错误1"),
        ExceptionGroup("内层错误", [
            TypeError("错误2"),
            OSError("错误3"),
        ]),
    ])
except* ValueError as e:
    print(f"捕获到 ValueError: {e}")
except* TypeError as e:
    print(f"捕获到 TypeError: {e}")
except* OSError as e:
    print(f"捕获到 OSError: {e}")
# ExceptionGroup 可以同时抛出和捕获多个异常

# 抛出异常组
def validate_user(data: dict) -> None:
    errors = []
    if "name" not in data:
        errors.append(ValueError("缺少 name"))
    if "age" not in data:
        errors.append(ValueError("缺少 age"))
    if "email" in data and "@" not in data["email"]:
        errors.append(TypeError("email 格式错误"))
    if errors:
        raise ExceptionGroup("用户数据校验失败", errors)

# 使用 except* 分别处理不同类型的异常
try:
    validate_user({"name": "Alice"})
except* ValueError as e:
    print(f"值错误: {e.exceptions}")
except* TypeError as e:
    print(f"类型错误: {e.exceptions}")

# ExceptionGroup 支持嵌套
try:
    raise ExceptionGroup("外层错误", [
        ValueError("错误1"),
        ExceptionGroup("内层错误", [
            TypeError("错误2"),
            OSError("错误3"),
        ]),
    ])
except* ValueError as e:
    print(f"捕获到 ValueError: {e}")
except* TypeError as e:
    print(f"捕获到 TypeError: {e}")
except* OSError as e:
    print(f"捕获到 OSError: {e}")

异常链 ​

python
# 使用 raise...from 保留原始异常上下文
try:
    1 / 0
except ZeroDivisionError as e:
    raise RuntimeError("计算失败") from e
# 使用 raise...from 保留原始异常上下文
try:
    1 / 0
except ZeroDivisionError as e:
    raise RuntimeError("计算失败") from e