从零开始:Python语言进阶之异常处理

一、认识异常:程序运行中的“意外事件”

 

在编写Python程序时,即使代码语法完全正确,运行过程中也可能遭遇各种意外情况。这些意外被称为异常,它们会打断程序的正常执行流程。例如,当我们尝试打开一个不存在的文件、用0作为除数进行除法运算,或者对不兼容的数据类型执行操作时,Python解释器就会抛出异常。

 

1.1 常见内置异常类型

 

Python提供了丰富的内置异常类,理解这些基础类型是掌握异常处理的第一步:

 

①  ZeroDivisionError :当尝试除以0时触发。例如:

result = 5 / 0  # 立即引发ZeroDivisionError

②  FileNotFoundError :使用 open() 函数打开不存在的文件时出现。例如:

f = open('nonexistent.txt', 'r')  # 找不到文件会引发此异常

③  TypeError :操作或函数作用于不匹配的数据类型。例如:

text = "hello"
length = len(text) + 10  # 正确,但 len(text) + "10" 会引发TypeError

④  ValueError :数据的值不符合预期格式。例如:

num = int("abc")  # 无法转换为整数,引发ValueError

1.2 异常的本质:特殊对象

 

每个异常都是一个对象,继承自内置的 BaseException 类。当异常发生时,Python会创建一个对应类型的异常对象,并沿着调用栈向上传递,直到被捕获或导致程序终止。例如, ZeroDivisionError 异常对象包含了错误类型和发生错误的上下文信息。

 

二、基础异常处理:try - except语句

 

2.1 基础语法结构

 

 try - except 是Python处理异常的核心语句,其结构如下:

try:# 可能引发异常的代码块pass
except ExceptionType:# 捕获到指定类型异常时执行的代码pass

①  try 块:放置可能产生异常的代码,例如文件操作、数据转换等。

②  except 块:用于捕获并处理特定类型的异常。如果 try 块中的代码引发异常,程序会立即跳转到对应的 except 块执行。

 

2.2 简单示例

 

以文件读取为例:

try:file = open('test.txt', 'r')content = file.read()file.close()
except FileNotFoundError:print("文件不存在")

在这个例子中:

 

1.  try 块尝试打开并读取 test.txt 文件。

2. 如果文件不存在, open() 函数会引发 FileNotFoundError 异常。

3. 程序跳转到 except 块,打印“文件不存在”,避免程序崩溃。

 

2.3 捕获多个异常类型

 

可以使用多个 except 块处理不同类型的异常:

try:num = int(input("请输入一个整数:"))result = 10 / num
except ValueError:print("输入的不是有效的整数")
except ZeroDivisionError:print("除数不能为0")

这里分别捕获了 ValueError (输入非整数)和 ZeroDivisionError (输入0作为除数),提供更细致的错误反馈。

 

三、扩展异常处理:else与finally子句

 

3.1 else子句:无异常时执行

 

 else 子句紧跟在 except 块之后,仅在 try 块未引发任何异常时执行:

try:num = int("10")
except ValueError:print("转换失败")
else:print(f"转换后的整数是:{num}")  # 仅当try块无异常时执行

else 子句常用于分离正常逻辑和异常处理逻辑,让代码结构更清晰。

 

3.2 finally子句:无论如何都会执行

 

 finally 子句用于确保某些代码始终被执行,无论 try 块是否引发异常:

file = None
try:file = open('test.txt', 'r')data = file.read()
except FileNotFoundError:print("文件未找到")
finally:if file:file.close()  # 确保文件资源被释放

在Python 3.4+中,推荐使用 with 语句替代手动 finally 块关闭文件:

try:with open('test.txt', 'r') as file:data = file.read()
except FileNotFoundError:print("文件未找到")

with 语句会自动管理资源的打开和关闭,相当于隐式的 finally 操作。

 

四、自定义异常:贴合业务需求

 

4.1 为什么需要自定义异常

 

内置异常适用于通用错误,但在实际项目中,我们常需根据业务逻辑定义专属异常。例如在用户注册系统中,可能需要处理“用户名已存在”“密码格式错误”等特定问题,此时自定义异常能让错误处理更清晰。

 

4.2 定义和使用自定义异常

 

自定义异常类通常继承自 Exception 类或其子类:

class UsernameExistsError(Exception):passdef register_user(username):existing_usernames = ["user1", "user2"]if username in existing_usernames:raise UsernameExistsError(f"用户名 {username} 已存在")print(f"用户 {username} 注册成功")try:register_user("user1")
except UsernameExistsError as e:print(e)

步骤解析:

 

1. 定义 UsernameExistsError 类继承自 Exception 。

2.  register_user 函数在检测到用户名重复时,使用 raise 语句抛出异常。

3. 外层通过 try - except 捕获并处理该异常。

 

五、常见问题与解决方案

 

5.1 问题一:捕获所有异常(过于宽泛)

 

问题描述:使用 except: 捕获所有异常,包括程序逻辑错误和系统退出异常(如 KeyboardInterrupt ),导致错误难以排查。

错误示例:

try:result = 1 / 0
except:print("发生了错误")  # 无法区分具体错误类型

解决方案:明确指定异常类型,或使用多个 except 块分别处理:

try:result = 1 / 0
except ZeroDivisionError:print("除数不能为0")

5.2 问题二:异常丢失

 

问题描述:异常在函数调用链中未被正确传递或处理,导致无法定位问题根源。

错误示例:

def inner_function():return 1 / 0def outer_function():try:inner_function()except:pass  # 异常被“吃掉”,无法定位问题outer_function()

解决方案:使用 raise 重新抛出异常,或记录日志后再处理:

def inner_function():try:return 1 / 0except ZeroDivisionError:raise  # 重新抛出异常def outer_function():try:inner_function()except ZeroDivisionError:print("捕获到内层函数的除零异常")outer_function()

5.3 问题三:性能损耗

 

问题描述:频繁使用异常处理会因栈回溯等操作影响性能。

解决方案:优先使用条件判断避免异常,仅对真正不可预测的错误使用异常处理。例如:

divisor = 0
if divisor != 0:result = 10 / divisor
else:print("除数不能为0")

六、总结:打造健壮的程序

 

掌握异常处理是编写可靠Python程序的关键。通过 try - except 捕获异常、 else 和 finally 细化逻辑、自定义异常适配业务,再结合对常见问题的规避,我们能够让程序在面对意外时优雅应对,而不是突然崩溃。记住:异常处理不是万能药,合理的逻辑设计才是减少异常的根本。

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

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

相关文章

Groovy:Java 的简洁版

Groovy 是一种 动态、面向对象的编程语言,运行在 Java 虚拟机(JVM)上,并与 Java 高度兼容。你可以把它理解为“Java 的简洁版 动态特性 脚本语言的灵活性”。 🧠 Groovy 的核心特点 特性说明✅ 与 Java 高度兼容可以…

生成模型——PixelRNN与PixelCNN

一、PixelRNN PixelRNN 是一种基于循环神经网络(RNN)的像素级生成模型,通过逐个像素地生成图像来构建完整的图像,其核心思想是将图像中的像素视为序列,并利用 RNN 的能力来捕捉像素之间的依赖关系。 序列生成&#xf…

每日算法刷题Day14 5.24:leetcode不定长滑动窗口求子数组个数越长越合法4道题,用时1h20min

3. 3325.字符至少出现K次的子字符串I(中等,学习优化) 3325. 字符至少出现 K 次的子字符串 I - 力扣(LeetCode) 思想 1.给你一个字符串 s 和一个整数 k,在 s 的所有子字符串中,请你统计并返回 至少有一个 字符 至少…

怎么判断一个Android APP使用了Capacitor这个跨端框架

要判断一个 Android 应用是否使用了 Capacitor 跨端框架,可以通过以下方法逐步验证: 一、安装包结构分析 1. 解压 APK 将 .apk 文件重命名为 .zip 并解压,检查以下特征文件: • assets/public/ 目录: Capacitor 的核心…

Vue3性能优化: 大规模列表渲染解决方案

# Vue3性能优化: 大规模列表渲染解决方案 一、背景与挑战 背景 在大规模应用中,Vue3的列表渲染性能一直是开发者关注的焦点。大规模列表渲染往往会导致卡顿、内存占用过高等问题,影响用户体验和系统整体性能。 挑战 渲染大规模列表时,DOM操作…

数据仓库,扫描量

有五种通用技术用于限制数据的扫描量,正如图3 - 4所示。第一种技术是扫描那些被打上时戳的数据。当一个应用对记录的最近一次变化或更改打上时戳时,数据仓库扫描就能够很有效地进行,因为日期不相符的数据就接触不到了。然而,目前的…

反射在spring boot自动配置的应用

目录 一,背景 二,知识回顾 2.1 理解使用反射技术,读取配置文件创建目标对象(成员变量,方法,构造方法等) 三,springboot自动配置 3.1 反射在自动配置中的工作流程 3.2 浏览源码…

机器学习 Day1

机器学习概述 机器学习与人工智能、深度学习关系什么是机器学习数据集算法 机器学习与人工智能、深度学习关系 什么是机器学习 机器学习是从数据中自动分析获取模型,并利用模型对未知数据进行预测。 直观理解: 所以是从历史数据中获取规律,那么这些历…

Disruptor—2.并发编程相关简介

大纲 1.并发类容器 2.volatile关键字与内存分析 3.Atomic系列类与UnSafe类 4.JUC常用工具类 5.AQS各种锁与架构核心 6.线程池的最佳使用指南 1.并发类容器 (1)ConcurrentMap (2)CopyOnWrite容器 (3)ArrayBlockingQueue (4)LinkedBlockingQueue (5)SynchronousQueue …

开盘啦 APP 抓包 逆向分析

声明: 本文章中所有内容仅供学习交流使用,不用于其他任何目的,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关! 抓包 这是一个记录贴。 这个APP是数…

YOLOv8损失函数代码详解(示例展示数据变换过程)

本文将展示YOLOv8中损失函数计算的完整代码解析,注释中提供了详尽的解释,并结合示例演示了数据维度的转换,以帮助更好地理解。 YOLOv8的损失函数计算代码位于ultralytics/utils/loss.py文件中(如下所示),我…

微信小程序调用蓝牙API “wx.writeBLECharacteristicValue()“ 报 errCode: 10008 的解决方案

1、问题现象 问题:在开发微信小程序蓝牙通信功能时,常常会遇到莫名其妙的错误,查阅官方文档可能也无法找到答案。如在写入蓝牙数据时,报了这样的错误: {errno: 1500104, errCode: 10008, errMsg: "writeBLECharacteristicValue:fail:system error, status: UNKNOW…

软考 UML中的 用例图 的泛化 包含 扩展 关系

用例图的泛化、扩展和包含 - ^_^肥仔John - 博客园

MyBatis-Plus的自带分页方法生成的SQL失败:The error occurred while setting parameters

1、error描述 数据库是postgres,Java使用mybatis-plus的分页功能,生成的分页SQL不能正常运行。 "msg": "nested exception is org.apache.ibatis.exceptions.PersistenceException: Error querying database. Cause: com.baomidou.my…

Redis从入门到实战 - 原理篇

一、数据结构 1. 动态字符串SDS 我们都知道Redis中保存的key是字符串,value往往是字符串或者字符串的集合。可见字符串是Redis中最常用的一种数据结构。 不过Redis没有直接使用C语言中的字符串,因为C语言字符串存在很多问题: 获取字符串长…

人形机器人通过观看视频学习人类动作的技术可行性与前景展望

摘要 本文深入探讨人形机器人通过观看视频学习人类动作这一技术路线的正确性与深远潜力。首先阐述该技术路线在模仿人类学习过程方面的优势,包括对人类动作、表情、发音及情感模仿的可行性与实现路径。接着从技术原理、大数据训练基础、与人类学习速度对比等角度论证…

高分辨率北半球多年冻土数据集(2000-2016)

关键数据集分类&#xff1a;冰冻圈数据集时间分辨率&#xff1a;10 year < x < 100 year空间分辨率&#xff1a;1km - 10km共享方式&#xff1a;开放获取数据大小&#xff1a;339.79 MB数据时间范围&#xff1a;2000-01-01 — 2016-12-31元数据更新时间&#xff1a;2022-…

零售智能执行大模型架构设计:从空间建模到上下文推理,再到智能Agent

零售智能执行大模型架构设计&#xff1a;从空间建模到上下文推理&#xff0c;再到智能Agent &#x1f9e0; 引言&#xff1a;零售智能执行的再定义 在传统零售执行中&#xff0c;面对SKU数量庞杂、货架布置多变、陈列标准难以落地等问题&#xff0c;靠人力巡检或轻量识别模型已…

RIP 协议实验全记录:从配置到问题解决

在网络世界中&#xff0c;路由协议就像是交通指挥员&#xff0c;引导数据在不同网络之间顺畅传输。今天&#xff0c;我们就来深入探索 RIP&#xff08;Routing Information Protocol&#xff09;协议&#xff0c;通过一系列实验&#xff0c;揭开它的神秘面纱&#xff01; 一、搭…

基于SpringBoot的网上租赁系统设计与实现

项目简介 本项目是基于 Spring Boot Vue 技术栈开发的 网上租赁系统。该系统通过前后端分离的架构&#xff0c;提供用户和管理员两种角色的操作权限&#xff0c;方便用户进行商品租赁、订单管理、信息查询等操作&#xff0c;同时也为管理员提供了商品管理、用户管理、订单管理…