Python异常是运行期出错时抛出的对象。不处理就会让程序中断。用 try / except 按类型接管错误,可选的 else 在未出错时执行,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:,它连系统退出类信号也可能吞掉:

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:总会执行

无论是否进过 exceptfinally 都会跑。关文件、释放锁这类收尾逻辑常放这里:

开始 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 时,更具体的类型要写在更宽的类型前面,例如 ValueErrorException 之前。
  • except: pass 会让故障悄无消失,至少打印或记录异常信息。