写在前面

程序总会出错:用户输入了不是数字的东西、列表取了下标越界、字典里没有你要的键……出错不可怕,可怕的是一出错程序就整个崩掉。Python 的异常处理机制让你能优雅地接住错误、给出提示,甚至继续往下运行。这篇带你掌握 try/except 的完整用法。

先认识 Traceback

不做任何处理时,Python 会打印一段 Traceback 然后退出:

nums = [1, 2, 3]
print(nums[10])
# IndexError: list index out of range

最后一行是异常类型和说明,往上的箭头指出错在哪一行。读懂它,你就已经解决了一半的问题。

try/except 基本用法

把可能出错的代码放进 try,出错时执行的代码放进 except:

nums = [1, 2, 3]
try:
    print(nums[10])
except IndexError:
    print("下标超出范围了")
# 输出:下标超出范围了

异常被接住后,程序不会崩溃,会继续执行后面的代码。

捕获特定异常类型

建议总是写清楚异常类型,别用一只大网兜住所有错误:

text = "abc"
try:
    number = int(text)
except ValueError:
    print(f"{text} 不是合法数字")
# 输出:abc 不是合法数字

scores = {"语文": 92}
try:
    print(scores["数学"])
except KeyError:
    print("没有这门科目的成绩")
# 输出:没有这门科目的成绩

try:
    print(10 / 0)
except ZeroDivisionError:
    print("除数不能为零")
# 输出:除数不能为零

一个 try 也可以跟多个 except,分别接不同类型的错误,还可以用 as err 拿到异常对象:

try:
    number = int("xyz")
except ValueError as err:
    print(f"转换失败:{err}")
# 输出:转换失败:invalid literal for int() with base 10: 'xyz'

else 与 finally

else 在没出错时执行,finally 无论出不出错都会执行,常用来收尾(比如关闭文件):

def to_number(text):
    try:
        number = int(text)
    except ValueError:
        print("转换失败")
    else:
        print(f"转换成功:{number}")
    finally:
        print("本次处理结束")

to_number("42")
# 输出:
# 转换成功:42
# 本次处理结束

to_number("abc")
# 输出:
# 转换失败
# 本次处理结束

主动抛出异常

写函数时,遇到不合法的参数可以用 raise 主动报错,提醒调用者改正:

def set_age(age):
    if age < 0:
        raise ValueError("年龄不能是负数")
    print(f"年龄已设置为 {age}")

set_age(18)
# 输出:年龄已设置为 18

try:
    set_age(-1)
except ValueError as err:
    print(f"参数错误:{err}")
# 输出:参数错误:年龄不能是负数

小结

这篇文章我们学会了:读懂 Traceback 定位错误、用 try/except 接住特定异常、用 else/finally 组织更清晰的结构,以及用 raise 对非法参数主动说不。异常处理是代码健壮性的第一道防线,从今天起,写任何可能出错的输入处理时都记得套上它。下一篇我们聊聊 Python 的文件读写实战。