程序运行时难免出错,比如用户输错数据、文件找不到、网络突然断开。错误处理能让程序:

  1. 不崩溃:遇到问题能稳住,给用户友好提示而不是直接闪退。
  2. 好维护:快速定位问题在哪,不用像猜谜一样排查。
  3. 更健壮:意外情况早有预案,比如重试连接或切换备用方案。

简单说就是:让程序像老司机,爆胎了还能安全靠边,而不是直接翻车

一、什么是异常(错误)

程序正常运行时,遇到非法操作、数据错误、文件不存在、网络失败、索引越界等问题,会直接终止程序、抛出红色报错,这就是异常。错误处理作用:

  1. 不让程序直接崩溃闪退
  2. 捕获错误、打印友好提示
  3. 出错后可以兜底执行代码、释放资源
  4. 主动拦截非法数据,规范代码逻辑

二、核心语法:try /except

基础结构:

try:
    # 有可能报错的代码,写在这里
    可能出错的逻辑
except:
    # 一旦 try 里代码报错,立刻执行这里
    错误兜底逻辑

基础范例(无错误处理 vs 错误处理)

# 无错误处理:除数为0,程序直接崩溃
# a = 10 / 0

# 加错误处理:捕获异常,程序正常运行
try:
    a = 10 / 0
except:
    print("代码出错了,不能除以0")

三、捕获指定异常(重点推荐)

不建议直接写裸except,会隐藏所有 bug。指定捕获某一种错误,其他错误正常报错,方便调试。

try:
    num = int("abc")
except ValueError:
    print("类型错误:字符串无法转为数字")

四、获取错误详情 as e

可以接收异常对象,打印系统原始错误信息,方便排查问题。

try:
    result = 20 / 0
except ZeroDivisionError as e:
    # e 就是错误详情
    print("捕获到错误:", e)

五、同时捕获多种异常

写法 1:多个异常写在一个括号内

try:
    data = [1,2,3][5]
except (ZeroDivisionError, IndexError, ValueError) as e:
    print("触发范围类错误:", e)

写法 2:分开捕获,不同错误不同处理

try:
    f = open("test.txt", "r")
    num = int("kkk")
except FileNotFoundError:
    print("错误:文件不存在")
except ValueError:
    print("错误:数据格式非法")
except Exception as e:
    # Exception 是所有异常的父类,放在最后兜底
    print("未知错误:", e)

六、else 分支:无报错才执行

try 代码完全正常、没有异常时,才会走 else 代码块。

try:
    age = int("25")
except ValueError:
    print("格式错误")
else:
    print("转换成功,年龄为:", age)

七、finally 分支:无论对错必执行

不管代码报错与否,finally 里的代码100% 执行。核心用途:关闭文件、断开连接、释放内存、销毁资源。

f = None
try:
    f = open("test.txt", "r", encoding="utf-8")
    content = f.read()
except FileNotFoundError:
    print("文件不存在")
finally:
    # 无论是否报错,都关闭文件
    if f:
        f.close()
        print("文件已强制关闭")

八、常用内置异常(开发高频)

日常写代码只需要熟记这些:

  1. ValueError:数值 / 格式错误,字符串转数字失败
  2. ZeroDivisionError:除以零错误
  3. IndexError:列表 / 字符串索引越界
  4. KeyError:字典找不到 key
  5. TypeError:数据类型不匹配
  6. FileNotFoundError:文件不存在
  7. AttributeError:对象没有这个属性 / 方法(类开发常用)

九、主动抛出异常 raise

不止捕获错误,还可以手动主动抛错。用来校验数据、限制传参,不符合规则直接拦截。

基础用法

def set_age(age):
    if age < 0 or age > 150:
        # 主动抛出指定异常
        raise ValueError("年龄必须在0~150之间")
    print("年龄设置成功:", age)

# 合法数据
set_age(20)
# 非法数据,主动报错
# set_age(-5)

十、自定义异常(结合前面 类 的知识点)

Python 允许自己写异常类,继承内置 Exception 父类,适合大型项目、自定义业务报错。完全复用之前学的 class 类语法。

# 自定义业务异常
class UserError(Exception):
    # 继承系统异常父类
    pass

class PasswordError(Exception):
    pass

# 模拟登录校验
def login(username, pwd):
    if not username:
        raise UserError("用户名不能为空")
    if len(pwd) < 6:
        raise PasswordError("密码长度不能小于6位")

# 测试捕获自定义异常
try:
    login("", "123")
except UserError as e:
    print("账号错误:", e)
except PasswordError as e:
    print("密码错误:", e)

十一、嵌套异常处理

复杂逻辑支持多层 try 嵌套,局部错误局部捕获,不影响整体流程。

try:
    print("外层逻辑开始")
    try:
        1 / 0
    except ZeroDivisionError:
        print("内层:捕获除零错误")
except:
    print("外层全局兜底")

十二、综合实战案例(整合全部知识点)

输入数字、除法计算、完整容错,贴近实际业务:

def calc_div():
    try:
        a = int(input("请输入第一个数字:"))
        b = int(input("请输入第二个数字:"))
        res = a / b
    except ValueError:
        print("错误:必须输入纯数字")
    except ZeroDivisionError:
        print("错误:第二个数字不能为0")
    except Exception as e:
        print("未知错误:", e)
    else:
        print("计算结果:", res)
    finally:
        print("计算流程结束")

calc_div()

十三、开发最佳实践(必看)

  1. 禁止无脑裸 except:,优先捕获指定异常,保留调试能力
  2. 兜底统一用 except Exception 放在最后,不要滥用
  3. 资源操作(文件、数据库、网络)必须搭配 finally 释放
  4. 业务校验用 raise 主动抛错,规范入参
  5. 大型项目使用自定义异常类,区分系统错误和业务错误
  6. 不要用异常代替正常判断,能 if 判断的逻辑,优先用 if

快速知识点总结

  1. try 包裹高危代码,except 捕获异常
  2. as e 接收错误信息,方便定位问题
  3. else 无报错执行,finally 强制兜底执行
  4. raise 手动抛出异常,用于数据校验
  5. 自定义异常:新建类继承 Exception
  6. 错误处理 + 前面学的类 / 接口,是项目稳定运行的核心组合
Logo

这里是“一人公司”的成长家园。我们提供从产品曝光、技术变现到法律财税的全栈内容,并连接云服务、办公空间等稀缺资源,助你专注创造,无忧运营。

更多推荐