Python自定义异常类:实际应用示例之最佳实践

news2024/11/29 3:52:50

在这里插入图片描述

Python自定义异常类:实际应用示例之最佳实践

前言

在软件开发中,合理处理异常是保证程序稳定性的重要环节。虽然 Python 内置了丰富的异常类型,但在处理复杂业务逻辑时,自定义异常类能够使代码更加清晰且具备可扩展性。

本文将通过几个实际的应用场景,展示如何使用 Python 自定义异常类来增强代码的可读性与维护性。

示例1:库存管理系统中的异常处理

场景描述

在一个库存管理系统中,当用户试图购买某个商品时,系统需要检查库存是否充足。如果库存不足,系统需要抛出一个特定的异常来通知调用方进行处理,而不仅仅是抛出一个通用的异常。

解决方案

在这种场景下,我们可以定义一个 InventoryShortageException 来处理库存不足的情况。

class InventoryShortageException(Exception):
    def __init__(self, item_id, requested, available):
        self.item_id = item_id
        self.requested = requested
        self.available = available
        super().__init__(f"商品 {item_id} 库存不足:请求数量 {requested},仅剩 {available} 件。")


class InventoryService:
    def check_inventory(self, item_id, requested_quantity):
        inventory = self.get_inventory(item_id)
        if inventory < requested_quantity:
            raise InventoryShortageException(item_id, requested_quantity, inventory)
        return True

    def get_inventory(self, item_id):
        # 模拟获取库存信息
        return 5


# 测试
try:
    service = InventoryService()
    service.check_inventory("A1001", 10)
except InventoryShortageException as e:
    print(f"捕获到异常:{e}")

分析

在上述代码中,当库存不足时,InventoryShortageException 被抛出,并带有商品ID、请求数量及剩余库存等详细信息。捕获到异常后,系统可以进一步执行如通知供应商补货等后续逻辑。

优势

  • 清晰明确的异常类型提高了可读性。
  • 提供了丰富的上下文信息,便于后续处理。
  • 通过自定义异常,业务逻辑与异常处理分离,增强了系统的可维护性。

示例2:用户注册系统中的数据验证异常

场景描述

在用户注册系统中,通常需要对用户提交的数据进行验证,比如检查用户名是否已存在、邮箱格式是否正确等。为此,我们可以定义多个自定义异常类来处理不同类型的数据验证错误,使得调用方可以根据具体的错误类型做出相应处理。

解决方案

通过定义多个自定义异常类,如 UsernameAlreadyExistsExceptionInvalidEmailFormatException,可以精确地处理不同的验证错误。

class UsernameAlreadyExistsException(Exception):
    pass


class InvalidEmailFormatException(Exception):
    pass


class UserService:
    def register_user(self, username, email):
        if self.check_username_exists(username):
            raise UsernameAlreadyExistsException(f"用户名 {username} 已存在")
        if not self.validate_email(email):
            raise InvalidEmailFormatException(f"邮箱 {email} 格式不正确")
        # 模拟用户注册逻辑
        print(f"用户 {username} 注册成功")

    def check_username_exists(self, username):
        # 模拟用户名已存在的情况
        existing_users = ["user1", "user2"]
        return username in existing_users

    def validate_email(self, email):
        # 简单的邮箱格式校验
        return "@" in email and "." in email


# 测试
try:
    service = UserService()
    service.register_user("user1", "example.com")
except UsernameAlreadyExistsException as e:
    print(f"捕获到异常:{e}")
except InvalidEmailFormatException as e:
    print(f"捕获到异常:{e}")

分析

在用户注册时,如果用户名已存在或邮箱格式不正确,系统分别抛出 UsernameAlreadyExistsExceptionInvalidEmailFormatException。捕获到不同类型的异常后,系统可以针对性地提示用户进行修改,确保用户体验。

优势

  • 细化了异常处理,便于调用方对不同错误做出不同反应。
  • 自定义异常类可以与具体的业务逻辑密切结合,提高代码的可读性。
  • 通过多个自定义异常,系统能更灵活地处理用户输入错误,增强了用户交互体验。

示例3:使用 traceback 定位异常位置

场景描述

在用户注册系统中,当发生数据验证错误时,开发者希望能够快速定位到抛出异常的位置,以便进行调试和修复。通过使用 traceback 模块,可以在捕获异常时输出详细的堆栈跟踪信息。

解决方案

在捕获异常时,使用 traceback.print_exc() 来输出异常的堆栈跟踪信息。

import traceback


class UsernameAlreadyExistsException(Exception):
    pass


class InvalidEmailFormatException(Exception):
    pass


class UserService:
    def register_user(self, username, email):
        if self.check_username_exists(username):
            raise UsernameAlreadyExistsException(f"用户名 {username} 已存在")
        if not self.validate_email(email):
            raise InvalidEmailFormatException(f"邮箱 {email} 格式不正确")
        # 模拟用户注册逻辑
        print(f"用户 {username} 注册成功")

    def check_username_exists(self, username):
        # 模拟用户名已存在的情况
        existing_users = ["user1", "user2"]
        return username in existing_users

    def validate_email(self, email):
        # 简单的邮箱格式校验
        return "@" in email and "." in email


# 测试
try:
    service = UserService()
    service.register_user("user1", "example.com")
except (UsernameAlreadyExistsException, InvalidEmailFormatException) as e:
    print(f"捕获到异常:{e}")
    print("堆栈跟踪信息如下:")
    traceback.print_exc()

分析

在这个示例中,当 UsernameAlreadyExistsExceptionInvalidEmailFormatException 被抛出时,traceback.print_exc() 会输出异常的堆栈跟踪信息。这些信息包括异常发生的文件名、行号和调用栈,帮助开发者快速定位到问题代码的位置。

优势

  • 快速定位:通过堆栈跟踪信息,开发者可以迅速找到抛出异常的具体位置。
  • 详细信息:堆栈跟踪提供了丰富的上下文信息,便于分析和解决问题。
  • 调试便利:在调试过程中,能够快速获取异常的详细信息,提高了问题解决的效率。

总结

通过本文的三个示例,我们展示了自定义异常类和 traceback 模块在复杂业务场景中的实际应用:

  1. 库存管理系统中的异常处理:通过自定义异常类 InventoryShortageException,我们能够清晰地处理库存不足的情况,并提供详细的上下文信息,便于后续处理。
  2. 用户注册系统中的数据验证异常:通过定义多个自定义异常类,如 UsernameAlreadyExistsExceptionInvalidEmailFormatException,我们可以细化异常处理,针对不同的验证错误做出相应的反应,提高用户体验。
  3. 使用 traceback 定位异常位置:在捕获异常时,使用 traceback.print_exc() 输出详细的堆栈跟踪信息,帮助开发者快速定位和解决问题。

自定义异常类和 traceback 的结合使用,不仅提高了代码的可读性和可维护性,还增强了系统的错误处理能力,使得系统具备更好的可扩展性和调试效率。

后话

本次分享到此结束,

see you~~✨✨

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2206309.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一个架构师的职业素养:四种常用的权限模型

你好,我是看山。 本文收录在《一个架构师的职业素养》专栏。日拱一卒,功不唐捐。 今天咱们一起聊聊权限系统。 以大家熟知的电商场景举例: 用户可以分为普通用户、VIP用户:我们需要控制不同角色用户的访问范围。比如,京东的PLUS会员,可以进入会员专区,而且能够使用礼金…

ESP32接入扣子(Coze) API使用自定义智能体

使用ESP32接入Coze API实现聊天机器人的教程 本示例将使用ESP32开发板通过WiFi接入 Coze API&#xff0c;实现一个简单的聊天机器人功能。用户可以通过串口向机器人输入问题&#xff0c;ESP32将通过Coze API与智能体进行通信&#xff0c;并返回对应的回复。本文将详细介绍了如…

OpenGL 进阶系列03 - OpenGL实例化渲染来提高性能

目录 一:概述 二:实例化渲染的优点: 三:OpenGL实例化渲染的例子: 一:概述 OpenGL 实例化渲染(Instanced Rendering)是一种渲染技术,可以有效地绘制多个相同对象,而不需要为每个对象单独提交绘制调用。通过这种方式,可以显著提高渲染性能,尤其是在需要绘制大量相…

【每日刷题】Day137

【每日刷题】Day137 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. 1576. 替换所有的问号 - 力扣&#xff08;LeetCode&#xff09; 2. 495. 提莫攻击 - 力扣&#xf…

【数据结构与算法】线性表顺序存储结构

文章目录 一.顺序表的存储结构定义1.1定义1.2 图示1.3结构代码*C语言的内存动态分配 二.顺序表基本运算*参数传递2.1建立2.2初始化(InitList(&L))2.3销毁(DestroyList(&L))2.4判断线性表是否为空表(ListEmpty(L))2.5求线性表的长度(ListLength(L))2.6输出线性表(DispLi…

基于GoogleNet深度学习网络的手语识别算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) 手语How are you&#xff0c;测试识别结果如下&#xff1a; 手语I am fine&#xff0c;测试识别结果如下&#xff1a; 手…

java入门和Java语法

Java直接运行源代码文件&#xff0c;不会产生HelloWorld.class第二种方法&#xff1a;把模块放在D盘下&#xff0c;然后导入 第三种方法&#xff1a;新建一个模块&#xff0c;然后把内容复制过去 byte l 12; short m l; System.out.println(m); char n a; int reason mn; Sy…

消息摘要算法

算法特点 a) 消息摘要算法/单向散列函数/哈希函数 b) 不同长度的输入&#xff0c;产生固定长度的输出 c) 散列后的密文不可逆 d) 散列后的结果唯一 e) 哈希碰撞 f) 一般用于校验数据完整性、签名sign 由于密文不可逆&#xff0c;所以服务端也无法解密 想要验证&#xf…

解锁机器人视觉与人工智能的潜力,从“盲人机器”改造成有视觉能力的机器人(下)

机器视觉产业链全景回顾 视觉引导机器人生态系统或产业链分为三个层次。 上游&#xff08;供应商&#xff09; 该机器人视觉系统的上游包括使其得以运行的硬件和软件提供商。硬件提供商提供工业相机、图像采集卡、图像处理器、光源设备&#xff08;LED&#xff09;、镜头、光…

如何让信息学奥赛学习“边玩边学”?——趣味编程让枯燥学习变得有趣

信息学奥赛&#xff08;NOI&#xff09;作为一项高水平的编程竞赛&#xff0c;内容涉及到大量的算法、数据结构和复杂的逻辑思维&#xff0c;对学生的要求非常高。然而&#xff0c;面对枯燥的知识点和高难度的题目&#xff0c;很多学生在备赛过程中容易感到乏味甚至放弃。那么&…

Overfrp内网穿透:使用域名将内网http/https服务暴露到公网

项目地址&#xff1a;https://github.com/sometiny/overfrp 使用overfrp部署穿透服务器&#xff0c;绑定域名后&#xff0c;可使用域名访问内网的http/https服务。 用例中穿透服务器和内网机器之间的访问全链路加密&#xff0c;具有ssh2相当的安全级别。&#xff01;&#xf…

国外电商系统开发-运维系统秘钥管理

文件上传功能&#xff0c;都是通过拖放的方式上传的 当然了&#xff0c;上面我只是演示行的放几个文件而已&#xff0c;不要在意文件名。此时&#xff0c;如果您有服务器是通过SSH-Key登录的&#xff0c;那么在服务器配置中&#xff0c;您可以做如下选择&#xff1a;

【论文阅读】Learning a Few-shot Embedding Model with Contrastive Learning

使用对比学习来学习小样本嵌入模型 引用&#xff1a;Liu, Chen, et al. “Learning a few-shot embedding model with contrastive learning.” Proceedings of the AAAI conference on artificial intelligence. Vol. 35. No. 10. 2021. 论文地址&#xff1a;下载地址 论文代码…

jenkins 插件SSH Pipeline Steps

一、安装 SSH Pipeline Steps | Jenkins plugin 二、添加全局linux服务器用户名密码&#xff1a;linux-142 三、新建流水线SshServer 添加Pipeline Script node {def remote [:]remote.name tstremote.host 192.168.31.142remote.allowAnyHosts truewithCredentials([usern…

leetcode167. 两数之和 II - 输入有序数组

给你一个下标从 1 开始的整数数组 numbers &#xff0c;该数组已按 非递减顺序排列 &#xff0c;请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] 和 numbers[index2] &#xff0c;则 1 < index1 < index2 < numbers…

操作系统中的并发控制——使用条件变量同步

本期主题&#xff1a; 操作系统中的并发控制&#xff0c;条件变量 往期链接&#xff1a; linux设备驱动中的并发操作系统中的多线程问题——原子操作、自旋锁的底层实现操作系统并发控制——使用互斥锁实现同步 操作系统并发控制之条件变量同步 1. 问题描述2. 条件变量的API讲…

数据治理、数据清洗定义、区别以及数据清洗常用方法

一、数据治理定义 数据治理是一种组织数据管理的方法&#xff0c;涉及数据的收集、存储、处理、分析和共享等方面&#xff0c;旨在最大程度地利用数据资产并降低数据相关的风险。‌ 数据治理确保数据的质量、安全性、合规性和可用性&#xff0c;以支持组织的决策和运营活动。‌…

【Canvas与标牌】2024.10.8胜利大逃亡盾形标牌

【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>537.日期金盾Draft2上色</title><style type"text/css…

用Raspberry Pi Imager重装树莓派系统

今天删东西的时候&#xff0c;无意中把系统文件给remove了&#xff0c;结果树莓派无法正常启动&#xff0c;只能重新安装。 用DiskGenius工具将SD卡彻底清空&#xff0c;并将boot分区和文件分区合并为一&#xff0c;之后再对这个新分区进行了格式化。接下来就是烧录镜像了。以…

Java知识巩固(二)

OKracle JDK vs OpenJD 可能在看这个问题之前很多人和我一样并没有接触和使用过 OpenJDK 。那么 Oracle JDK 和 OpenJDK 之间是否存在重大差异&#xff1f;下面我通过收集到的一些资料&#xff0c;为你解答这个被很多人忽视的问题。 首先&#xff0c;2006 年 SUN 公司将 Java…