Python 中的异常处理机制,是保证程序在运行过程中遇到错误时不会直接崩溃的重要工具

发布时间:2026/10/17 2:39:44

Python 中的异常处理机制,是保证程序在运行过程中遇到错误时不会直接崩溃的重要工具 Python 中的异常处理机制是保证程序在运行过程中遇到错误时不会直接崩溃的重要工具。程序在运行中难免会出现各种意外情况例如用户输入了不合法的数据、文件不存在、网络请求失败、数据类型转换错误等。如果没有异常处理程序一旦遇到错误就会立即终止用户体验较差维护成本也会增加。try-except结构让开发者可以主动捕获运行错误并对错误进行记录、提示、恢复或降级处理从而提高程序的健壮性和可用性。一、异常处理的基本概念异常是程序在运行过程中出现的非正常事件。它不同于语法错误。语法错误通常发生在代码编写阶段例如少写了冒号、括号不匹配、变量名拼写错误等这类错误会导致程序无法运行。而异常发生在程序已经成功启动之后在执行某条语句时出现了问题。例如将一个字符串转换为整数时如果字符串内容是abcPython 就无法完成转换会抛出ValueError。又例如访问列表中不存在的下标时会抛出IndexError。再例如使用open()打开一个不存在的文件时可能会抛出FileNotFoundError。这些都属于运行时异常。异常处理的核心思想不是“让程序永远不报错”而是“在错误发生时让程序能够以可控的方式处理错误”。开发者可以决定是提示用户重新输入、记录日志、返回默认值还是关闭资源后重新抛出异常。二、try-except的基本结构Python 中最基础的异常处理结构如下try:# 可能出错的代码except异常类型:# 捕获到异常后的处理代码下面是一个简单的示例try:numberint(input(请输入一个整数))print(你输入的数字是,number)exceptValueError:print(输入不合法请输入一个整数。)在这段代码中try块中放置了可能出错的代码。如果用户输入的是12程序会正常转换为整数并输出结果如果用户输入的是helloint()函数会抛出ValueError程序不会直接崩溃而是进入except ValueError分支输出提示信息。需要注意的是except后面最好明确写出要捕获的异常类型例如ValueError、ZeroDivisionError、FileNotFoundError等。如果只写except:虽然也能捕获异常但会掩盖更多问题不利于排查错误。三、捕获多种异常程序中的某一段代码可能同时存在多种错误风险。此时可以使用多个except分支分别处理不同异常。try:aint(input(请输入被除数))bint(input(请输入除数))resulta/bprint(结果是,result)exceptValueError:print(输入错误请输入整数。)exceptZeroDivisionError:print(除数不能为 0。)exceptExceptionase:print(发生未知错误,e)这段代码中ValueError用于处理用户输入不是整数的情况ZeroDivisionError用于处理除数为 0 的情况最后一个except Exception as e用于捕获其他未预料到的异常。as e可以把异常对象保存下来方便输出错误信息。从工程实践角度看except Exception通常放在多个except的最后作为兜底处理。它不应该替代具体异常类型的捕获因为过于宽泛的异常捕获可能会隐藏真正的程序问题。四、else子句的作用try-except结构还可以配合else使用。else中的代码只有在try块没有发生异常时才会执行。try:numberint(input(请输入一个整数))exceptValueError:print(输入不合法。)else:print(输入成功数字是,number)这里将“输入转换”和“输入成功后的处理”分开逻辑更清晰。try块只负责执行可能出错的操作else块负责执行没有异常时才应该执行的后续逻辑。使用else的好处是可以避免把过多代码放进try块中。如果try块中包含大量无关代码一旦其中某一行出错可能会影响异常定位。把安全代码放入else有助于缩小异常捕获范围。五、finally子句的作用finally子句中的代码无论是否发生异常都会执行。它通常用于释放资源、关闭文件、关闭数据库连接、结束计时等操作。try:fopen(test.txt,r)contentf.read()print(content)exceptFileNotFoundError:print(文件不存在。)finally:print(程序结束执行清理操作。)即使文件不存在程序进入except分支finally中的代码仍然会执行。如果文件正常打开并读取成功finally同样会执行。因此finally非常适合放置“必须执行”的收尾代码。更推荐的做法是使用with语句管理文件资源try:withopen(test.txt,r)asf:contentf.read()print(content)exceptFileNotFoundError:print(文件不存在。)with语句可以在离开代码块时自动关闭文件即使发生异常也会正确释放资源。但在某些复杂场景中例如同时涉及网络、数据库、文件、锁等多种资源时finally仍然具有重要价值。六、完整执行流程示例下面通过一个综合示例展示try-except-else-finally的完整执行顺序defdivide():try:aint(input(请输入被除数))bint(input(请输入除数))resulta/bexceptValueError:print(输入格式错误。)exceptZeroDivisionError:print(除数不能为 0。)else:print(计算成功结果是,result)finally:print(本次除法操作结束。)divide()当输入合法且除数不为 0 时程序会执行try和else最后执行finally。当输入不是整数时程序会执行except ValueError和finally。当除数为 0 时程序会执行except ZeroDivisionError和finally。因此finally的确定性执行特性使其成为资源清理和日志记录的重要位置。七、常见异常类型Python 中常见的异常类型包括异常类型说明ValueError值类型不正确例如无法将abc转为整数TypeError操作数类型不支持该操作IndexError列表或序列下标越界KeyError字典中不存在指定键FileNotFoundError文件不存在ZeroDivisionError除数为 0AttributeError对象没有某个属性或方法ImportError导入模块失败RuntimeError运行时一般性错误Exception大多数内置异常的基类在实际开发中应尽量捕获最具体的异常类型而不是直接使用except Exception。例如读取字典键时应该优先捕获KeyError而不是捕获所有异常。八、主动抛出异常除了捕获异常程序也可以主动抛出异常。使用raise可以在检测到不合法状态时中断当前逻辑并向调用者传递错误信息。defset_age(age):ifnotisinstance(age,int):raiseTypeError(年龄必须是整数。)ifage0orage150:raiseValueError(年龄必须在 0 到 150 之间。)print(年龄设置成功,age)try:set_age(-5)exceptValueErrorase:print(参数错误,e)主动抛出异常可以让错误更早暴露。例如在函数入口处检查参数合法性如果参数不符合要求就立即抛出异常而不是让错误在更深层的代码中逐渐扩散。这样有利于定位问题也便于上层调用者统一处理错误。九、自定义异常当系统内置异常不足以表达业务含义时可以自定义异常类。自定义异常通常继承自Exception并可以携带更具体的错误信息。classInsufficientBalanceError(Exception):def__init__(self,message,balance):super().__init__(message)self.balancebalanceclassBankAccount:def__init__(self,owner,balance0):self.ownerowner self.balancebalancedefwithdraw(self,amount):ifamount0:raiseValueError(取款金额必须大于 0。)ifamountself.balance:raiseInsufficientBalanceError(余额不足。,self.balance)self.balance-amountprint(取款成功当前余额,self.balance)accountBankAccount(张三,100)try:account.withdraw(200)exceptInsufficientBalanceErrorase:print(e,当前余额,e.balance)exceptValueErrorase:print(e)这个示例中InsufficientBalanceError比普通的Exception更能表达业务含义。调用者可以根据不同异常类型做出不同处理例如提示用户充值、记录风控日志或返回特定错误码。十、异常处理的最佳实践异常处理并不是写得越多越好。良好的异常处理应当遵循以下原则不要滥用裸except直接写except:会捕获几乎所有异常包括键盘中断、系统退出等可能导致程序难以调试。优先捕获具体异常能明确知道可能出现的异常类型时应直接捕获该类型例如ValueError、KeyError、FileNotFoundError。缩小try块范围try块中只放入可能出错的代码不要把大量无关逻辑都放进去否则异常来源会变得不清晰。不要掩盖真正的问题捕获异常后应进行合理处理例如提示用户、记录日志、恢复状态或重新抛出异常。如果只是pass掉异常可能会让错误隐藏起来。合理使用else和finallyelse适合放置无异常时才执行的逻辑finally适合放置必须执行的清理逻辑。日志记录比简单打印更可靠在生产环境中建议使用logging模块记录异常信息而不是只使用print()。日志可以保留时间、级别、模块和堆栈信息。区分用户错误和程序错误用户输入错误可以友好提示程序内部错误应记录日志并尽快修复。不能把所有问题都简单归为“用户操作不当”。十一、综合应用示例下面给出一个较为完整的综合示例展示异常处理在小型程序中的实际用法importlogging logging.basicConfig(filenameapp.log,levellogging.INFO,format%(asctime)s - %(levelname)s - %(message)s)defread_number(prompt):whileTrue:try:valuefloat(input(prompt))exceptValueError:print(请输入有效的数字。)logging.warning(用户输入了无效数字。)else:returnvaluedefsafe_divide(a,b):try:returna/bexceptZeroDivisionError:logging.error(发生除零错误a%s, b%s,a,b)returnNonedefmain():try:aread_number(请输入被除数)bread_number(请输入除数)resultsafe_divide(a,b)ifresultisnotNone:print(结果是,result)else:print(计算失败请检查输入。)exceptKeyboardInterrupt:print(\n程序已被用户中断。)logging.info(用户中断程序。)exceptExceptionase:print(程序发生错误,e)logging.exception(程序发生未预期错误。)finally:print(程序运行结束。)if__name____main__:main()这个程序首先通过read_number()反复要求用户输入直到输入合法数字为止。这里使用了try-except-else结构如果转换成功就通过else返回结果如果失败就提示用户重新输入。safe_divide()专门处理除零错误并在发生错误时记录日志。main()函数中捕获了用户中断异常KeyboardInterrupt也保留了兜底的except Exception最后通过finally输出程序结束提示。十二、总结try-except是 Python 异常处理的核心结构。它使程序能够在出现运行错误时保持可控而不是直接崩溃。try用于包裹可能出错的代码except用于捕获并处理对应异常else用于执行无异常时的后续逻辑finally用于执行无论是否异常都需要完成的收尾工作。合理使用异常处理可以让程序更稳定、更易维护也能为用户提供更好的交互体验。对于开发者而言异常处理不仅是语法知识更是一种防御式编程思想。程序应当尽量假设输入可能不合法、文件可能缺失、网络可能中断、数据可能异常并提前设计处理方式。通过具体异常捕获、合理日志记录、资源清理和自定义异常等手段可以显著提升 Python 程序的可靠性和可维护性。
延伸阅读

更多相关文章

2026/10/17 2:34:44

科捷智能职位分析:数据架构师

本文严格依据科捷智能官方工作职责、任职资格,结合智能制造、装备制造、项目制交付企业业务特性,对标DAMA、华为数据之道两大权威体系,系统性拆解数据架构师岗位定位、必备专业知识、核心软硬技能、岗位职责、简历优化策略、高频面试真题及标…

2026/10/17 2:34:44

密码学信任的底层逻辑:计算困难性理论与安全参数全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 3:49:49

Ubuntu 22.04安装CARLA 0.9.16全指南:从显卡驱动到libomp5排障

把CARLA 0.9.16装进Ubuntu 22.04这件事,老实说比想象中要坎坷。作为一个常年泡在仿真环境里的人,我原本以为解压压缩包、配两条环境变量就能跑起来,结果在显卡驱动和系统依赖上各栽了一次跟头。这篇笔记就是给准备在Ubuntu 22.04上装CARLA 0.…

2026/10/17 3:49:49

Qt OpenGL 连续图像显示优化:从 QLabel 掉帧到 GPU 渲染管线实战

简介:这份资源面向具备一定C与QT基础的开发者,聚焦于在QT控件中高效显示连续图像这一常见但性能敏感的场景,核心方案是采用QOpenGLWidget借助GPU硬件加速替代QLabel与QWidget的传统绘制方式。资源包共16个文件,包含6个jpg示例图片…

2026/10/17 3:49:49

BMI160六轴IMU官方驱动与Datasheet实战:从寄存器配置到姿态解算

简介:这份资源面向嵌入式开发、物联网设备及智能穿戴方向的工程师与学习者,提供博世BMI160六轴惯性测量单元(三轴加速度计三轴陀螺仪)的官方驱动源码与数据手册,可用于运动追踪、姿态检测与方向感知等场景的硬件集成。…

2026/10/17 3:49:49

有品味的AI画图:从能画到能用的设计规范与实操指南

1. 当AI画图开始讲“品味”,它到底在解决什么问题大多数人用AI画图,第一反应是“给我画个好看的图”。但“好看”这个词本身就是个陷阱——它太主观、太模糊,不同的人对好看的定义天差地别。更麻烦的是,当你需要一张用于正式场合的…

2026/10/17 3:49:49

AI辅助期刊论文写作:4类工具、完整工作流与避坑指南

“AI写论文”这四个字,放在学术群里永远是热度最高的话题。我最初对这类工具的态度很保守,毕竟第一次见到有人直接把大模型生成的一大段文字贴在论文里时,我看到的是编造的参考文献和不存在的实验记录。后来我自己处理一个期刊稿件&#xff0…

2026/10/17 3:44:49

基于深度学习的焊接缺陷检测系统实战:从数据到YOLOv8部署

焊接缺陷检测这件事,我在这个圈子里摸爬滚打了几年,看过太多传统视觉方案在现场翻车。早几年大家还在用边缘检测、阈值分割那套经典图像处理流程,遇到背景干净、打光均匀的工件还能硬撑一下,可一旦碰上飞溅、弧光、油污混杂的焊缝…

2026/10/16 5:33:43

Python调用Gemini Structured Outputs实现工单路由门禁

客服工单最怕的不是模型“答错一句话”,而是它给出一段看起来合理的说明,程序却从中猜错优先级。通俗做法是:要求模型只交 JSON(JavaScript Object Notation,轻量数据格式),再让代码验证它。Gem…

2026/10/16 4:03:48

Spring Boot超市进销存系统毕设实战:从需求拆解到答辩通关

最近带的一个学生项目组里,有A同学跑来问我:选什么毕设题目最稳妥,既能让评审老师觉得工作量够,又不会在答辩时被问到语无伦次。我第一反应就是推荐基于Spring Boot的超市仓库管理系统——也就是超市进销存系统。这个题目乍一看平…

2026/10/15 13:42:16

Flutter StatefulWidget 生命周期核心解析

很多刚开始接触 Flutter 的朋友,在看完一堆“Hello World”和基础组件之后,大概率都会撞上同一堵墙:StatefulWidget 里那堆 initState、build、dispose 方法,到底什么时候被调用?为什么顺序是那样?在里面到…

2026/10/17 0:04:32

PlanarSLAM:面向曼哈顿世界的点线面联合SLAM系统

简介:本资源是面向机器人视觉与SLAM研究者的C开源RGB-D SLAM系统实现,专为结构化室内场景(如办公室、走廊)设计,通过融合点、线、平面三类几何特征并引入“曼哈顿世界”假设,显著提升位姿跟踪鲁棒性与稠密地…

2026/10/17 0:04:32

TDH Workflow调度实战:从DAG依赖驱动到任务编排与故障排查

1. 从一个调度脚本说起:TDH Workflow到底在解决什么问题第一次接触TDH的Workflow,是在一个数据清洗项目里。当时团队每天要跑几十个ETL任务,任务之间有严格的先后依赖——A表清洗完才能跑B表的关联,B表跑完才能触发C表的聚合。最开…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑