资讯详情

Pyhton编程 - 第10章 错误和异常

📅 2026/10/18 14:00:25 | 华诺云谱 👁 阅读
Pyhton编程 - 第10章 错误和异常
第10章 错误和异常10.1 错误和异常的介绍Python是一门解释型语言只有在程序运行后才会执行语法检查。所以只有在运行或测试程序时才会真正知道该程序能不能正常运行。Python有两种错误很容易辨认语法错误和异常。10.1.1 语法错误程序解析时遇到的语法错误。 演示语法错误 print(以上代码有语法错误FileD:\PythonProject\chapter10\p01_syntax_error.py,line4print(^SyntaxError语法错误:(was never closed10.1.2 异常Python 程序的语法是正确的在运行它的时候也有可能发生错误。运行期检测到的错误被称为异常。大多数的异常都不会被程序处理都以错误信息的形式打印出来错误信息的前面部分显示了异常发生的上下文并以调用栈的形式显示具体信息。 演示异常 result3/0print(result)以上代码语法正确但是运行报错Traceback(most recent call last):FileD:\PythonProject\chapter10\p02_exception_error.py,line4,inmoduleresult3/0~~^~~ZeroDivisionError:division by zero除数为0的异常10.2 异常处理对异常进行处理并不是将错误规避了而是当程序运行的时候出现错误的时候提供解决方案不终止程序可以让程序继续执行。10.2.1 try except可以使用 try except 语句来捕获异常并处理。语法格式try:可能发生异常的代码except异常类型1:异常处理的代码except异常类型2:异常处理的代码except(异常类型3,异常类型4,异常类型5):异常处理的代码except:异常处理的代码如果try没有发生异常程序会忽略except中的代码继续向下执行。如果try发生了异常会忽略try中剩余代码根据异常类型匹配到相应的 except 并执行其中的代码。如果try发生了异常且异常类型无法和任何except匹配也没有独立的except:分支异常将向外传递。一个except可以同时处理多个异常将这些异常放在一个元组中。最后一个 except 可以忽略异常类型它将被作为通配符使用。演示案例 异常处理 whileTrue:try:aint(input(请输入被除数))bint(input(请输入除数))print(f{a}/{b}{a/b})breakexcept(ValueError,TypeError):print(必须输入整数)exceptZeroDivisionError:print(除数不能为0)except:print(未知错误)print(End)10.2.2 获取异常描述信息语法格式try:可能发生异常的代码except异常类型1as变量名1:异常处理的代码except异常类型2as变量名2:异常处理的代码except(异常类型3,异常类型4,异常类型5)as变量名3:异常处理的代码except:异常处理的代码except的异常类型后面加as 变量名当发生这个类型的异常时异常对象就会被赋值给这个变量。单独的except后面不能加变量名。打印traceback.print_exc()可以打印异常的详细信息示例代码 异常处理 importtracebackwhileTrue:try:aint(input(请输入第一个数字))bint(input(请输入第二个数字))print(f{a}/{b}{a/b})breakexceptValueErrorase:# traceback.print_exc() # 打印异常的详细信息print(输入错误请重新输入。异常信息是,e)exceptZeroDivisionErrorase:print(除数不能为0。异常信息是,e)except:print(未知错误)print(End)10.2.3 else可选地将else放在所有except之后。如果try中代码没有发生异常将执行 else 中的代码。语法格式try:可能发生异常的代码except异常类型1【as变量名1】:#【as 变量名1】表示可选的异常处理的代码except异常类型2【as变量名2】:异常处理的代码except(异常类型3,异常类型4,异常类型5)【as变量名3】:异常处理的代码except:异常处理的代码else:try中没有异常才执行的代码从执行效果上说将代码放到else块和直接放到try块中是一样的。将try正常执行完毕而没有引发任何异常后被执行的代码放到else中。提供了一种清晰的逻辑区分将正常情况的代码与异常处理代码分开使代码更易于理解和维护有助于代码的可读性和可维护性。示例代码 异常处理与else whileTrue:try:aint(input(请输入第一个数字))bint(input(请输入第二个数字))resulta/bexceptValueError:print(输入错误请重新输入)exceptZeroDivisionError:print(除数不能为0)except:print(未知错误)else:print(f{a}/{b}{result})breakprint(End)10.2.4 finally可选地放在最后。无论是否发生异常都会执行的代码通常用于执行一些必须要进行的清理操作例如关闭文件、释放资源如网络连接、数据库连接、锁等即使在执行 try 块中的代码时出现了异常也能保证这些操作得以完成。语法格式try:可能发生异常的代码except异常类型1【as变量名1】:#【as 变量名1】表示可选的异常处理的代码except异常类型2【as变量名2】:异常处理的代码except(异常类型3,异常类型4,异常类型5)【as变量名3】:异常处理的代码except:异常处理的代码else:try中没有异常才执行的代码finally:无论是否发生异常都会执行的代码finally 语句块是 try-except 结构的一部分它确保了无论 try 块中是否发生异常也不管 except 块是否可以捕获异常其中的代码都会被执行。如果从执行效果上说大部分场景将代码放到finally语句和放到try-except块外效果是一样的。但是直接放在try-except结构外面的代码只会在try-except结构正常执行完毕后才会执行如果在try块中出现异常且没有被except块捕获那么这部分代码将不会被执行。示例代码 演示finally块的执行特点 try:aint(input(请输入第一个数字))bint(input(请输入第二个数字))resulta/bexceptValueError:print(输入错误请重新输入)else:print(f{a}/{b}{result})finally:print(finally)print(End)10.3 抛出异常10.3.1 raise当你想要在代码中明确表示发生了错误或异常情况时可以使用 raise 来抛出异常。这可以帮助你在满足某些条件时停止程序的正常执行并将控制权转移到异常处理部分。语法格式raise异常类型(异常描述)案例演示# 定义Account类classAccount:def__init__(self,balance):self.__balancebalancedefwithdraw(self,amount):ifamount0:raiseValueError(取款金额不能为负数)ifamountself.__balance:raiseValueError(余额不足)self.__balance-amountdefdeposit(self,amount):ifamount0:raiseValueError(存款金额不能为负数)self.__balanceamountpropertydefbalance(self):returnself.__balance# 测试accountAccount(1000)try:account.withdraw(-500)exceptValueErrorase:print(取款失败,e)try:account.deposit(-500)exceptValueErrorase:print(存款失败,e)try:account.withdraw(1500)exceptValueErrorase:print(取款失败,e)try:account.withdraw(500)print(取款成功余额为,account.balance)exceptValueErrorase:print(取款失败,e)10.3.2 assertassert用于判断一个表达式在表达式条件为False的时候触发异常常用于调试程序。语法格式assert表达式[,异常描述]等价于ifnot表达式:raiseAssertionError([异常描述])案例演示 演示assert断言 # 待测试函数defadd(a,b):returnabdefmultiply(a,b):returna*b# 单元测试轻量版deftest_math_functions():# 验证加法assertadd(2,3)5,加法函数错误23应等于5assertadd(-1,1)0,加法函数错误-11应等于0# 验证乘法assertmultiply(2,3)6,乘法函数错误2*3应等于6assertmultiply(0,5)0,乘法函数错误0*5应等于0print(所有测试用例通过)# 执行测试test_math_functions()# 输出所有测试用例通过# 若函数出错比如multiply返回ab则触发断言乘法函数错误2*3应等于610.4 异常的传递当存在 try 嵌套或函数嵌套时若内层出现了异常且在内层无法处理会将异常一层一层向外传递直到异常被处理或程序报错。# 定义计算三角形面积的函数defcalculate_triangle_area(a,b,c):计算三角形面积的函数ifabcoracborbcaora0orb0orc0:raiseValueError(输入的数字无法构成三角形)# 使用海伦公式计算面积p(abc)/2area(p*(p-a)*(p-b)*(p-c))**0.5returnarea# 处理三角形的函数defprocess_triangle():处理三角形的函数try:aint(input(请输入边长a的值))bint(input(请输入边长b的值))cint(input(请输入边长c的值))# 调用计算面积函数areacalculate_triangle_area(a,b,c)print(f三角形的面积为{area})exceptValueError:print(输入错误请重新输入)raise# 重新抛出异常给上层# 测试代码whileTrue:try:process_triangle()breakexceptValueErrorase:print(e)10.5 withPython中的with语句用于异常处理封装了try except finally编码范式提供了一种简洁的方式来确保资源的正确获取和释放同时处理可能发生的异常提高了易用性。使代码更清晰、更具可读性简化了文件流等公共资源的管理。10.5.1 语法格式语法格式withexpressionasvariable:# 代码块expression通常是一个对象或函数调用该对象需要是一个上下文管理器即实现了__enter__和__exit__方法。variable是可选的用于存储expression的__enter__方法的返回值。10.5.2 示例代码1、未正确关闭资源# 定义函数未在finally中关闭文件defnot_close_in_finally():fileNonetry:# file open(test.txt, r)fileopen(test.txt,w)file.write(bruce...)file.close()print(文件写入成功)exceptOSErrorase:print(文件写入失败,e)finally:iffile:print(文件是否关闭,file.closed)# 文件是否关闭 Falseelse:print(文件未打开)# 调用测试not_close_in_finally()2、在finally中正确关闭文件# 定义一个函数处理文件defuse_finally():fileNonetry:# file open(test.txt, r)fileopen(test.txt,w)file.write(bruce...)print(文件写入成功)exceptOSErrorase:print(文件写入失败,e)finally:iffile:file.close()print(文件已关闭)print(文件是否关闭,file.closed)# 文件是否关闭 Falseelse:print(文件未打开)# 测试use_finally()3、使用with关键字自动关闭文件# 定义一个函数处理文件defuse_with():try:# with open(test.txt, w) as file:withopen(test.txt,r)asfile:file.write(bruce...)print(文件写入成功)finally:print(文件是否关闭,file.closed)# 文件是否关闭 False# 测试use_with()10.5.3 工作原理当执行with语句时会调用expression对象的__enter__方法。__enter__方法的返回值可以被存储在 variable 中如果有以供 with 代码块中使用。然后执行 with 语句内部的代码块。无论在代码块中是否发生异常都会调用 expression 对象的__exit__方法以确保资源的释放或清理工作这类似于 try-except-finally 中的 finally 子句。close方法与__exit__方法的区别close是文件对象的普通方法用于显式关闭文件需要手动调用。如果在 close() 之前发生异常文件可能不会被关闭。__exit__是上下文管理器协议的特殊方法在 with 语句结束时自动调用由 Python 解释器自动调用。即使发生异常也会确保执行清理操作。10.6 异常类型Python 所有异常类的顶层根类是 BaseException所有异常都直接 / 间接继承它核心分支分「系统级异常」和「业务级异常」开发中常用的Exception是业务异常的父类。Python 异常继承的 3 个关键规则捕获父类 捕获所有子类捕获某个异常类时会自动捕获其所有直接 / 间接子类比如捕获LookupError会同时捕获IndexError和KeyError捕获顺序先子类后父类Python 按except的书写顺序匹配异常若父类写在子类前面子类异常会被父类 “拦截”导致精准捕获失效自定义异常必须继承 Exception而非 BaseException常见的部分异常类型异常子类异常子类异常说明BaseException根SystemExitsys.exit () 触发程序正常退出不建议捕获KeyboardInterruptCtrlC 触发用户主动中断不建议捕获Exception所有业务级异常的核心父类开发中 99% 的场景捕获此类及其子类SyntaxError编译时语法错误非运行时异常IndentationError缩进错误ArithmeticError算术运算通用异常封装各类数值计算错误ZeroDivisionError除法 / 取模运算除数为 0最常用的算术异常OverflowError数值运算结果超出可表示范围主要浮点数LookupError「查找失败」通用父类统一序列 / 字典的查找异常便于批量捕获IndexError列表 / 元组 / 字符串等序列索引越界KeyError字典访问不存在的键OSErrorPython3.3 整合 IOError成为系统 / IO 通用异常覆盖文件 / 系统相关错误FileNotFoundError只读模式打开不存在的文件 / 路径PermissionError对文件执行无权限操作读 / 写 / 执行IsADirectoryError对目录执行文件操作如 open 一个文件夹ImportError导入相关错误Python3.6 新增子类 ModuleNotFoundErrorNameError使用未定义的变量 / 函数 / 类子类 UnboundLocalError局部变量未绑定AttributeError访问对象不存在的属性 / 方法或修改不可变对象属性TypeError类型不匹配如数字 字符串相加、函数传参类型错误ValueError类型正确但值非法如 int (“abc”)子类 UnicodeError编码 / 解码错误StopIteration迭代器遍历完所有元素后继续调用__next__()AssertionErrorassert 语句条件为 False断言验证失败调试用10.7 自定义异常通过直接或者间接继承Exception类来创建自己的异常。例如 自定义异常 # 定义异常类classNotATriangleError(Exception):自定义异常类def__init__(self,message):self.messagemessagedef__str__(self):returnself.message# 测试whileTrue:try:aint(input(请输入第一个数字))bint(input(请输入第二个数字))cint(input(请输入第三个数字))ifabcoracborbcaora0orb0orc0:raiseNotATriangleError(输入的数字无法构成三角形)print(三角形的周长为,abc)breakexceptValueErrorase:print(输入错误请重新输入整数值,e)exceptNotATriangleErrorase:print(e)
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑