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

Python自定义异常类:实际应用示例之最佳实践
前言
在软件开发中,合理处理异常是保证程序稳定性的重要环节。虽然 Python 内置了丰富的异常类型,但在处理复杂业务逻辑时,自定义异常类能够使代码更加清晰且具备可扩展性。
本文将通过几个实际的应用场景,展示如何使用 Python 自定义异常类来增强代码的可读性与维护性。
示例1:库存管理系统中的异常处理
场景描述
在一个库存管理系统中,当用户试图购买某个商品时,系统需要检查库存是否充足。如果库存不足,系统需要抛出一个特定的异常来通知调用方进行处理,而不仅仅是抛出一个通用的异常。
解决方案
在这种场景下,我们可以定义一个 InventoryShortageException 来处理库存不足的情况。
class InventoryShortageException(Exception):def __init__(self, item_id, requested, available):self.item_id = item_idself.requested = requestedself.available = availablesuper().__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 Truedef 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:用户注册系统中的数据验证异常
场景描述
在用户注册系统中,通常需要对用户提交的数据进行验证,比如检查用户名是否已存在、邮箱格式是否正确等。为此,我们可以定义多个自定义异常类来处理不同类型的数据验证错误,使得调用方可以根据具体的错误类型做出相应处理。
解决方案
通过定义多个自定义异常类,如 UsernameAlreadyExistsException 和 InvalidEmailFormatException,可以精确地处理不同的验证错误。
class UsernameAlreadyExistsException(Exception):passclass InvalidEmailFormatException(Exception):passclass 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_usersdef 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}")
分析
在用户注册时,如果用户名已存在或邮箱格式不正确,系统分别抛出 UsernameAlreadyExistsException 或 InvalidEmailFormatException。捕获到不同类型的异常后,系统可以针对性地提示用户进行修改,确保用户体验。
优势
- 细化了异常处理,便于调用方对不同错误做出不同反应。
- 自定义异常类可以与具体的业务逻辑密切结合,提高代码的可读性。
- 通过多个自定义异常,系统能更灵活地处理用户输入错误,增强了用户交互体验。
示例3:使用 traceback 定位异常位置
场景描述
在用户注册系统中,当发生数据验证错误时,开发者希望能够快速定位到抛出异常的位置,以便进行调试和修复。通过使用 traceback 模块,可以在捕获异常时输出详细的堆栈跟踪信息。
解决方案
在捕获异常时,使用 traceback.print_exc() 来输出异常的堆栈跟踪信息。
import tracebackclass UsernameAlreadyExistsException(Exception):passclass InvalidEmailFormatException(Exception):passclass 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_usersdef 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()
分析
在这个示例中,当 UsernameAlreadyExistsException 或 InvalidEmailFormatException 被抛出时,traceback.print_exc() 会输出异常的堆栈跟踪信息。这些信息包括异常发生的文件名、行号和调用栈,帮助开发者快速定位到问题代码的位置。
优势
- 快速定位:通过堆栈跟踪信息,开发者可以迅速找到抛出异常的具体位置。
- 详细信息:堆栈跟踪提供了丰富的上下文信息,便于分析和解决问题。
- 调试便利:在调试过程中,能够快速获取异常的详细信息,提高了问题解决的效率。
总结
通过本文的三个示例,我们展示了自定义异常类和 traceback 模块在复杂业务场景中的实际应用:
- 库存管理系统中的异常处理:通过自定义异常类
InventoryShortageException,我们能够清晰地处理库存不足的情况,并提供详细的上下文信息,便于后续处理。 - 用户注册系统中的数据验证异常:通过定义多个自定义异常类,如
UsernameAlreadyExistsException和InvalidEmailFormatException,我们可以细化异常处理,针对不同的验证错误做出相应的反应,提高用户体验。 - 使用
traceback定位异常位置:在捕获异常时,使用traceback.print_exc()输出详细的堆栈跟踪信息,帮助开发者快速定位和解决问题。
自定义异常类和 traceback 的结合使用,不仅提高了代码的可读性和可维护性,还增强了系统的错误处理能力,使得系统具备更好的可扩展性和调试效率。
后话
本次分享到此结束,
see you~~✨✨
相关文章:
Python自定义异常类:实际应用示例之最佳实践
Python自定义异常类:实际应用示例之最佳实践 前言 在软件开发中,合理处理异常是保证程序稳定性的重要环节。虽然 Python 内置了丰富的异常类型,但在处理复杂业务逻辑时,自定义异常类能够使代码更加清晰且具备可扩展性。 本文将…...
创新设计大师项骅:用卓越才华打造医疗科技新未来
项骅,这位在设计界声名鹊起的才俊,正准备在其璀璨的职业生涯中开启一个激动人心的新篇章。近日,他宣布即将进军医疗科技领域,这一决定在设计圈和医疗界引起了广泛关注。项骅计划以UX设计师的身份,致力于改善医疗服务的用户体验。谈到这个新挑战,他显得兴致勃勃:"我期待将我…...
云计算第四阶段 CLOUD2周目 01-03
国庆假期前,给小伙伴们更行完了云计算CLOUD第一周目的内容,现在为大家更行云计算CLOUD二周目内容,内容涉及K8S组件的添加与使用,K8S集群的搭建。最重要的主体还是资源文件的编写。 (*^▽^*) 环境准备: 主机清单 主机…...
Linux搭建Hadoop集群(详细步骤)
前言 Hadoop是一个由Apache基金会所开发的分布式系统基础架构。用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力进行高速运算和存储。 说白了就是实现一个任务可以在多个电脑上计算的过程。 一:准备工具 1.1 VMware 1.2L…...
MongoDB中如何实现相似度查询
在 MongoDB 中,进行相似度查询通常涉及文本搜索或基于特定字段的相似度计算。以下是几种常见的方法: 1. 使用文本索引和文本搜索 MongoDB 提供了文本索引功能,可以对字符串字段进行全文搜索。你可以使用 $text 操作符来执行文本搜索查询。 …...
F开头的词根词缀:ful
60.-ful (1)表形容词,“有…的” grateful a 感激的(grate感激) rueful a 后悔的(rue悔恨) willful a 任性的(will意志…任意办事) tactful a 圆滑的(tact手腕…...
【python开发笔记】-- python装饰器
装饰器: 不修改被装饰对象的源代码,也不修改调用方式的前提下,给被装饰对象添加新的功能 原则:开放封闭原则 开放:对扩展功能(增加功能开放),扩展功能的意思是在源代码不做任何改变…...
WEB攻防-python考点CTF与CMS-SSTI模板注入PYC反编译
知识点: 1、PYC(python编译后的文件)文件反编译; 2、Python-Web-SSTI; 3、SSTI模板注入利用分析; (Server-Side Template Injection) SSTI 就是服务器端模板注入 当前使用的一…...
Open3D实现点云数据的序列化与网络传输
转载自个人博客:Open3D实现点云数据的序列化与网络传输 在处理点云数据的时候,有时候需要实现点云数据的远程传输。当然可以利用传输文件的方法直接把点云数据序列化成数据流进行传输,但Open3D源码在实现RPC功能时就提供了一套序列化及传输的…...
【C++11】右值引用
前言: 在C11中引入的右值引用(rvalue references)是现代C的一个重要特性,它允许开发者以更高效的方式处理临时对象(右值),避免不必要的拷贝,提升性能。右值引用通常与C11的**移动语义…...
CSS元素显示类型
display 属性是 CSS 中最重要的属性之一,主要用来控制元素的布局,通过 display 属性您可以设置元素是否显示以及如何显示。 根据元素类型的不同,每个元素都有一个默认的 display 属性值,例如<div>默认的 display 属性值为 …...
Flink 介绍(特性、概念、故障容错、运维部署、应用场景)
概述 特性 概念 数据流 状态 时间 savepoint 故障容错 运维部署 部署应用到任意地方 Flink能够更方便地升级、迁移、暂停、恢复应用服务 监控和控制应用服务 运行任意规模应用 应用场景 事件驱动型应用 什么是事件驱动型应用? 事件驱动型应用的优势 Flink如何…...
Python+Flask接口判断身份证省份、生日、性别、有效性验证+docker部署+Nginx代理运行
这里写目录标题 一、接口样式二、部署流程2.1 镜像打包2.1.1 准备工作2.1.2 build打包2.1.3 dokcer部署运行2.1.4 Nginx代理 三、代码及文件3.1 index.py3.2 areaCodes.json3.3 Dockerfile 一、接口样式 https://blog.henryplus.cn/idcardApi/idCard/query?idcard{idcard} 二、…...
门店收银营销活动打折特价-收银系统源码
1.功能描述 功能描述:连锁店总部/门店可以将商品设置第二件打折,如保温杯第一件10元,第二件5折; 2.适用场景 ☑新店开业、门店周年庆、节假日等特定时间促销; ☑会员拉新,设置会员专享套餐; …...
QTabWidget的每个tab居中显示图标和文本
使用QTabWidget,给每个tab添加了图标之后,文字和图标之间有间距,没有完美居中显示。 遇到此问题,尝试了多种办法,均不理想,最终自定义QTabBar,重绘tab,完美解决。 #include <QT…...
Ubuntu20.04如何安装Microsoft Edge浏览器?
Microsoft Edge是由微软开发的一款网页浏览器,首次发布于2015年,作为Windows 10操作系统的默认浏览器,取代了之前的Internet Explorer。 基于Chromium内核:自2019年起,Microsoft Edge转向了使用开源的Chromium内核,这使得它与Google Chrome在性能和兼容性方面有很多相似之…...
美团Java一面
美团Java一面 9.24一面,已经寄了 收到的第一个面试,表现很不好 spring bean生命周期 作用域(忘完了) 为什么用redis缓存 redis和数据库的缓存一致性问题 redis集群下缓存更新不一致问题 aop说一下 arraylist和linkedlist 数据库的…...
C#中ref关键字和out关键字
值传递和引用传递 值传递和引用传递是编程中涉及数据传递的两种方式。它们的主要区别在于数据是如何在函数或方法之间传递的。 值传递 值传递意味着当你把一个变量传递给一个函数时,实际上传递的是这个变量的值的一个拷贝。也就是说,函数内部对这个参数…...
贴吧软件怎么切换ip
在网络使用中,有时我们需要切换IP地址来满足特定的需求,比如需要切换贴吧软件IP以进行不同的操作。本文将介绍几种贴吧切换IP地址的方法,帮助用户更好地管理自己的网络身份和访问权限。 1、更换网络环境 通过连接到不同的Wi-Fi网络或使用移…...
图像分割恢复方法
传统的图像分割方法主要依赖于图像的灰度值、纹理、颜色等特征,通过不同的算法将图像分割成多个区域。这些方法通常可以分为以下几类: 1.基于阈值的方法 2.基于边缘的方法 3.基于区域的方法 4.基于聚类的方法 下面详细介绍这些方法及其示例代码。 1. 基…...
CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...
如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...
ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
push [特殊字符] present
push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...
华为OD机考-机房布局
import java.util.*;public class DemoTest5 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseSystem.out.println(solve(in.nextLine()));}}priv…...
