Python笔记(十三)--异常

这一节了解一下Python中的异常,它是程序执行过程中发生的错误事件,会中断正常流程。比如除以 0、访问不存在的字典键、打开不存在的文件,Python 都会抛出对应的异常对象。它能把"程序崩溃"变成"可控处理"。它让程序在出错时不会直接终止,而是按你预设的方式恢复、降级或记录。简单总结如下:

场景:

1.防止程序崩溃:捕获错误后程序可以继续运行,而不是直接退出。

2.提供错误恢复:出错时可以重试、回退到默认值、或切换到备用方案。

3.记录诊断信息:在except里记录日志和traceback,方便排查线上问题。

4.定义模块契约:用raise主动抛出异常,告诉调用方"这个条件不满足,无法继续"。

5.释放资源:通过finally或with保证文件、连接、锁等资源一定被释放。

API:

  1. try:异常捕获入口关键字,用来包裹有可能抛出异常的代码块,监控这段代码运行时是否产生异常。
python 复制代码
try:
    可能报错的代码
  1. except:捕获指定类型的异常,当try块抛出对应异常时,执行except内逻辑,可以单独捕获某一类异常。
python 复制代码
except 异常类型:
    异常处理逻辑
  1. except Exception as e:通用异常捕获写法,Exception是大部分内置异常的父类,把异常实例赋值给变量e,用于读取异常信息。
python 复制代码
except Exception as e:
    print(e)
  1. except (AError,BError):同时捕获多种指定异常,多个异常类型放到元组中,匹配其中任意一种都会进入分支。
python 复制代码
except (ValueError, ZeroDivisionError):
    统一处理这两类错误
  1. else:try代码块没有抛出任何异常的时候才会执行的分支,有异常则跳过else,适合放依赖try成功之后才执行的代码。
python 复制代码
try:
    正常代码
except:
    异常处理
else:
    无异常才执行
  1. finally:无论try里面是否发生异常、无论except有没有捕获到异常,最后一定会执行的代码块,常用于资源释放,关闭文件、连接。
python 复制代码
try:
    业务代码
finally:
    资源清理代码
  1. raise:主动抛出异常,手动触发指定异常,可以携带自定义异常提示信息。
python 复制代码
raise ValueError("参数不能小于0")
  1. raise from:链式抛出异常,关联原始异常,保存异常溯源关系,用于包装异常的时候保留底层报错。
python 复制代码
try:
    底层报错
except IOError as err:
    raise RuntimeError("上层业务失败") from err
  1. assert:断言,条件不成立的时候自动抛出AssertionError,多用于开发阶段校验前置条件,生产环境可以通过-O参数关闭断言。
python 复制代码
assert 条件, "断言失败提示"
  1. ValueError:值异常,传入参数类型正确但是数值不符合要求时抛出,比如把字符串转数字但内容不是数字。
python 复制代码
raise ValueError("数字范围非法")
  1. TypeError:类型异常,操作的数据类型不匹配,比如数字和字符串直接相加、函数传参数量不对。
python 复制代码
raise TypeError("参数类型错误")
  1. ZeroDivisionError:除零异常,除法或者取模运算分母为0的时候触发。
python 复制代码
10 / 0  # 自动抛出 ZeroDivisionError
  1. IndexError:索引异常,序列(列表、字符串)访问超出有效索引范围。
python 复制代码
lst = [1,2]
lst[5] # IndexError
  1. KeyError:字典键异常,访问字典不存在的key时抛出。
python 复制代码
d = {"a":1}
d["b"] # KeyError
  1. FileNotFoundError:文件不存在异常,打开一个不存在的文件触发,属于OSError子类。
python 复制代码
open("not_exist.txt")
  1. PermissionError:权限异常,文件读写但是没有对应操作系统权限,属于OSError子类。
python 复制代码
open("/root/xxx.txt","w") # 无权限时报错
  1. AttributeError:属性异常,对象访问不存在的属性或者方法。
python 复制代码
obj = 123
obj.test() # AttributeError
  1. NameError:名字异常,使用了没有定义的变量名。
python 复制代码
print(unknown_var) # NameError
  1. SyntaxError:语法异常,代码语法写错,解释器解析阶段报错,无法被try捕获
python 复制代码
if True  # 少冒号,SyntaxError
  1. BaseException:所有异常的顶层父类,包含Exception和系统退出类异常(KeyboardInterrupt、SystemExit),一般业务不要直接捕获BaseException。
python 复制代码
except BaseException as e:
    pass
  1. KeyboardInterrupt:键盘中断异常,用户按下Ctrl+C终止程序时抛出,属于BaseException子类。
python 复制代码
try:
    while True:
        pass
except KeyboardInterrupt:
    print("用户终止程序")
  1. sys.exc_info():sys模块API,返回当前捕获的异常元组 (异常类型,异常实例,追踪对象),适合在except内部获取完整异常信息。
python 复制代码
import sys
ty, val, tb = sys.exc_info()
  1. traceback.print_exc():traceback模块API,直接打印完整异常堆栈信息,比print(e)信息更全,调试用。
python 复制代码
import traceback
traceback.print_exc()
  1. traceback.format_exc():traceback模块API,把异常堆栈转为字符串返回,方便日志保存,而不是直接打印。
python 复制代码
err_str = traceback.format_exc()
  1. Exception.str():异常实例内置方法,返回异常简短描述,print(e)底层调用这个方法。
python 复制代码
e = ValueError("test")
print(e.__str__())
  1. args:异常实例内置属性,是保存异常参数的元组,大部分内置异常第一个元素是提示文本。
python 复制代码
e = ValueError("参数错了")
print(e.args)
  1. NotImplementedError:未实现异常,面向对象开发中,基类抽象方法要求子类重写,没有重写就抛出这个异常。
python 复制代码
def func():
    raise NotImplementedError("子类必须实现该方法")

栗子:

python 复制代码
def div_calc():
    while True:
        try:
            raw_a = input("输入被除数:")
            raw_b = input("输入除数:")
            a = float(raw_a)
            b = float(raw_b)
            res = a / b
        except ValueError:
            print("异常:输入不是合法数字")
        except ZeroDivisionError:
            print("异常:除数不能为0")
        except KeyboardInterrupt:
            print("\n收到退出指令,结束计算")
            break
        else:
            print(f"计算结果 = {res:.2f}")
        finally:
            print("====本次运算一轮结束====\n")

if __name__ == "__main__":
    div_calc()
python 复制代码
import traceback

class RegisterError(Exception):
    pass

class PasswordTooShortError(RegisterError):
    pass

class UsernameExistError(RegisterError):
    pass

def check_username(name: str):
    if len(name) < 3:
        raise RegisterError("用户名长度至少3位")
    if name == "admin":
        raise UsernameExistError("admin账号已被占用")

def check_pwd(pwd: str):
    if len(pwd) < 6:
        raise PasswordTooShortError("密码长度不能小于6位")

def user_register(username, password):
    try:
        check_username(username)
        check_pwd(password)
        return "注册成功"
    except RegisterError as e:
        # 包装一层异常,保留原始异常链
        try:
            raise RuntimeError("注册校验失败") from e
        except RuntimeError as wrap_err:
            err_log = traceback.format_exc()
            print("【日志记录完整堆栈】\n", err_log)
            return f"注册失败:{wrap_err.__cause__}"

if __name__ == "__main__":
    print(user_register("ad", "123456"))
    print("-"*40)
    print(user_register("admin", "123456"))
    print("-"*40)
    print(user_register("user01", "123"))
    print("-"*40)
    print(user_register("user02", "12345678"))
相关推荐
日日大王学编程1 小时前
开源Agent项目记忆设计决策对比
python·ai·langchain·开源·ai编程
vipxieliang1 小时前
Python 魔法方法:让自定义对象更 Pythonic
python
动词ing1 小时前
【学习笔记】动态数码管显示
笔记·学习
陈年老古董1 小时前
ClickHouse 单机搭建记录
hive·笔记·学习·clickhouse·硬件架构
雨晨源码(同名B站)2 小时前
深度学习毕业设计选题推荐:基于YOLO11的交通标志检测系统设计与实现(Python+Django+Vue3+对接deepseek)
人工智能·python·深度学习·机器学习·django·课程设计
一级新生2 小时前
LLM _ Agent _ Skill _ 专家 的关系与选型笔记
java·开发语言·人工智能·笔记·大模型·智能体·skill
2601_967979122 小时前
python中str函数怎么用?使用方法与注意事项详解
python·使用方法·字符串转换·注意事项·str函数
青少儿编程课堂2 小时前
蓝桥杯青少组图形化+信息素养+电子学会Scratch考级:校园口算闯关解析
c++·python·算法·bfs·信息学竞赛
2603_969694852 小时前
【MySQL学习笔记】DQL(基础查询/条件/聚合/分组/排序/分页)与 DCL(用户权限)全解析
数据库·笔记·学习·mysql·学习方法