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

news2025/5/25 10:16:19

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

 

在编写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):
    pass

def 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 / 0

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

outer_function()

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

def inner_function():
    try:
        return 1 / 0
    except 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.coloradmin.cn/o/2385280.html

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

相关文章

如何制作可以本地联网搜索的MCP,并让本地Qwen3大模型调用搜索回答用户问题?

环境: SearXNG Qwen3-32B-FP8 vllm 0.8.5 问题描述: 如何制作可以本地联网搜索的MCP,并让本地Qwen3大模型调用搜索回答用户问题? 解决方案: 一、安装searxng 1.按需新建模型相关文件夹 mkdir MCP chmod 777 /mnt/program/MCP2.配置conda源 nano ~/.condarc nano…

服务器硬盘虚拟卷的处理

目前的情况是需要删除逻辑卷,然后再重新来弄一遍。 数据已经备份好了,所以不用担心数据会丢失。 查看服务器的具体情况 使用 vgdisplay 操作查看服务器的卷组情况: --- Volume group ---VG Name vg01System IDFormat …

一个国债交易策略思路

该国债交易策略的核心在于通过分析历史价格数据来识别市场趋势,并在趋势确认时进行开仓操作。策略的设计思路结合了价格波动范围的计算和市场波动性的评估,旨在捕捉市场的短期趋势并控制风险。 首先,策略通过对过去5根K线的最高价和最低价进行…

【三维重建】【3DGS系列】【深度学习】3DGS的理论基础知识之如何形成高斯椭球

【三维重建】【3DGS系列】【深度学习】3DGS的理论基础知识之如何形成高斯椭球 文章目录 【三维重建】【3DGS系列】【深度学习】3DGS的理论基础知识之如何形成高斯椭球前言高斯函数一维高斯多维高斯 椭球基本定义一般二次形式 3D高斯椭球3D高斯与椭球的关系各向同性(Isotropic)和…

手写ES6 Promise() 相关函数

手写 Promise() 相关函数: Promise()、then()、catch()、finally() // 定义三种状态常量 const PENDING pending const FULFILLED fulfilled const REJECTED rejectedclass MyPromise {/*定义状态和结果两个私有属性:1.使用 # 语法(ES2022 官方私有字…

【NLP 76、Faiss 向量数据库】

压抑与痛苦,那些辗转反侧的夜,终会让我们更加强大 —— 25.5.20 Faiss(Facebook AI Similarity Search)是由 Facebook AI 团队开发的一个开源库,用于高效相似性搜索的库,特别适用于大规模向…

软件名称:系统日志监听工具 v1.0

软件功能:一款基于 PyQt5 开发的 Windows 系统日志监听工具,适用于系统运维、网络管理、故障排查等场景,具备以下核心功能: 支持监听系统三大日志源:应用程序 / 系统 / 安全日志实时抓取新日志事件,自动滚…

Spring AI 之结构化输出转换器

截至 2024 年 2 月 5 日,旧的 OutputParser、BeanOutputParser、ListOutputParser 和 MapOutputParser 类已被弃用,取而代之的是新的 StructuredOutputConverter、BeanOutputConverter、ListOutputConverter 和 MapOutputConverter 实现类。后者可直接替换前者,并提供相同的…

Java虚拟机面试题:内存管理(上)

🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编…

进程间通信I·匿名管道

目录 进程间通信(IPC) 含义 目的 分类 匿名管道 原理 创建过程 特性 四大情况 close问题 代码练习 简单通信 进程池 小知识 进程间通信(IPC) 含义 就是让不同的进程能看到同一份资源,实现数据交流。 …

Ubuntu Linux系统的基本命令详情

1.Ubuntu Linux是以桌面应用为主的Linux发行版操作系统 2.Ubuntu的用户使用 在登录系统一般使用在安装系统时建立的普通用户登录,如果要使用超级用户权限 #sudo ---执行命令 sudo passwd ---修改用户密码 su - root ---切换超级用户 系统的不同,命令也不…

大数据治理:理论、实践与未来展望(二)

书接上文 文章目录 七、大数据治理的未来发展趋势(一)智能化与自动化(二)数据隐私与安全的强化(三)数据治理的云化(四)数据治理的跨行业合作(五)数据治理的生…

PCB布局设计

PCB布局设计 一、原理图到PCB转换前的准备工作 在将原理图转换为PCB之前,我们需要进行一系列准备工作,确保设计的正确性和完整性。这一步骤至关重要,可以避免后续PCB设计中出现不必要的错误。 // 原理图转PCB前必要检查步骤 // 1. 仔细检查…

esp32+IDF V5.1.1版本编译freertos报错

error: portTICK_RATE_MS undeclared (first use in this function); did you mean portTICK_PERIOD_MS 解决方法: 使用命令 idf.py menuconfig 打开配置界面配置freeRtos 使能configENABLE_BACKWARD_COMPATIBLITY

笔记本6GB本地可跑的图生视频项目(FramePack)

文章目录 (一)简介(二)本地执行(2.1)下载(2.2)更新(2.3)运行(2.4)生成 (三)注意(3.1)效…

SpringMVC实战:动态时钟

引言 在现代 Web 开发中,选择一个合适的框架对于项目的成功至关重要。Spring MVC 作为 Spring 框架的核心模块之一,以其清晰的架构、强大的功能和高度的可配置性,成为了 Java Web 开发领域的主流选择。本文将通过一个“动态时钟”的实战项目…

哈希表的实现(上)

前言 在C98中,STL提供了底层为红黑树结构的一系列关联式容器,在查询时效率可达到,即最差情况下需要比较红黑树的高度次,当树中的节点非常多时,查询效率也不理想。最好的查询是,进行很少的比较次数就能够将…

【Java高阶面经:微服务篇】1.微服务架构核心:服务注册与发现之AP vs CP选型全攻略

一、CAP理论在服务注册与发现中的落地实践 1.1 CAP三要素的技术权衡 要素AP模型实现CP模型实现一致性最终一致性(Eureka通过异步复制实现)强一致性(ZooKeeper通过ZAB协议保证)可用性服务节点可独立响应(支持分区存活)分区期间无法保证写操作(需多数节点可用)分区容错性…

实验7 HTTP协议分析与测量

实验7 HTTP协议分析与测量 1、实验目的 了解HTTP协议及其报文结构 了解HTTP操作过程:TCP三次握手、请求和响应交互 掌握基于tcpdump和wireshark软件进行HTTP数据包抓取和分析技术 2、实验环境 硬件要求:阿里云云主机ECS 一台。 软件要求&#xff1…

python:机器学习概述

本文目录: 一、人工智能三大概念二、学习方式三、人工智能发展史**1950-1970****1980-2000****2010-2017****2017-至今** 四、机器学习三要素五、常见术语六、数据集的划分七、常见算法分类八、机器学习的建模流程九、特征工程特征工程包括**五大步**:特…