在 Python 中,运行期错误以异常对象的形式抛出;若未捕获,程序将中断并打印回溯。使用 try / except 可按类型处理异常;else 在 try 未引发异常时执行,finally 无论是否异常均执行,常用于释放资源。需要主动报告错误条件时,使用 raise。本节说明上述结构及常见用法。

未捕获的异常

# print(10 / 0)          # ZeroDivisionError
# nums = [1, 2]
# print(nums[5])         # IndexError

上述错误若传播到顶层,解释器将打印回溯并终止。置于 try 内可改为提示信息并继续后续逻辑。

try / except

可为不同异常类型编写多个 except 分支;匹配到某一类型时,仅执行对应分支:

try:
    num = int(input("输入数字: "))
    print(10 / num)
except ZeroDivisionError:
    print("不能除以 0!")
except ValueError:
    print("那不是数字!")

输入 0 进入除零分支;输入非数字时,int(...) 引发 ValueError。

捕获更宽的异常

在具体类型之后,可使用 except Exception as e 捕获其余常见异常,并通过 e 获取说明。应尽量避免无类型的裸 except:,因其可能连 KeyboardInterrupt 等信号一并捕获:

try:
    result = 10 / int(input("除数: "))
    print(result)
except ZeroDivisionError:
    print("除数不能是 0")
except Exception as e:
    print("出了点问题:", e)

else:无异常时执行

else 须写在 except 之后,仅当 try 块未引发异常时执行,适合放置依赖成功结果的操作:

try:
    num = int(input("输入数字: "))
except ValueError:
    print("输入无效")
else:
    print(f"你输入了 {num}")

finally:必定执行

无论是否进入 except,finally 均会执行,关闭文件、释放锁等收尾逻辑常置于此:

开始 try:尝试执行 有异常? 是 except 处理异常 否 / 无异常 else 无异常才执行 finally 必执行 结束
try 里没报错走 else,报错进 except,finally 无论怎样都执行,适合放关文件、释放资源的清理代码。
try:
    f = open("demo.txt", "r")
    print(f.read())
except FileNotFoundError:
    print("文件不存在")
finally:
    print("清理步骤,总会执行")

打开文件时的异常处理

将读取置于 try 内,分别处理文件不存在与权限不足;成功读取后的后续步骤可放在 else 中:

try:
    with open("config.txt", "r", encoding="utf-8") as f:
        content = f.read()
except FileNotFoundError:
    print("配置文件不存在,使用默认配置")
    content = "default"
except PermissionError:
    print("没有读取权限")
else:
    print("读取成功,长度", len(content))

raise:主动抛出

参数不合法时,可直接 raise ValueError(...),由调用方决定如何处理:

Python raise 自定义异常示例运行
def set_age(age):
    if age < 0 or age > 150:
        raise ValueError(f"年龄不合法: {age}")
    return age

try:
    set_age(200)
except ValueError as e:
    print("捕获:", e)

常见错误

  • 捕获范围过宽(尤其裸 except:)可能掩盖本须处理的错误;优先捕获具体类型。
  • 多个 except 时,更具体的类型须写在更宽的类型之前,例如 ValueError 在 Exception 之前。
  • except: pass 会使故障静默消失,至少应记录或打印异常信息。

本节说明了 Python 中异常处理各子句的语义与 raise 的用法。下一节介绍迭代器:协议、for 循环及自定义可迭代类。