四时宝库

程序员的知识宝库

Python入门学习教程:第 12 章 异常处理

12.1 什么是异常?

在程序运行过程中,难免会出现各种错误。例如,试图打开一个不存在的文件、除以零、访问列表中不存在的索引等,这些错误在 Python 中被称为异常(Exception)。

当程序发生异常时,如果没有进行处理,程序会终止运行并抛出错误信息。例如:

# 除以零,会引发ZeroDivisionError异常

print(10 / 0)

运行结果:

Traceback (most recent call last):

File "test.py", line 1, in <module>

print(10 / 0)

ZeroDivisionError: division by zero

异常处理的目的是捕获程序运行中可能出现的错误,并进行相应的处理(如提示用户、记录日志等),而不是让程序直接崩溃,从而提高程序的健壮性。

12.2 异常处理的基本语法(try-except)

Python 使用try-except语句来处理异常,基本语法如下:

try:

# 可能发生异常的代码块

except 异常类型:

# 当发生指定类型的异常时,执行的代码块

执行流程:

  1. 执行try块中的代码。
  1. 如果try块中没有发生异常,则跳过except块,继续执行后续代码。
  1. 如果try块中发生了指定类型的异常,则立即停止执行try块,转而执行except块中的代码。
  1. 如果发生的异常类型与except指定的类型不匹配,则程序仍然会终止并抛出错误。

示例:处理除以零的异常

try:

num1 = 10

num2 = 0

result = num1 / num2 # 此处会发生ZeroDivisionError异常

print("计算结果:", result) # 发生异常后,这句代码不会执行

except ZeroDivisionError:

print("错误:除数不能为零!")

print("程序继续执行...") # 异常被处理后,程序会继续执行这句

运行结果:

错误:除数不能为零!

程序继续执行...

12.3 捕获多种异常

一个try块中可能发生多种类型的异常,可以使用多个except块分别处理不同的异常,也可以在一个except块中处理多种异常。

12.3.1 多个 except 块

try:

# 可能发生多种异常的代码

num = int(input("请输入一个整数:"))

result = 10 / num

print("结果:", result)

except ValueError:

print("错误:输入的不是有效的整数!")

except ZeroDivisionError:

print("错误:除数不能为零!")

运行示例 1(输入非整数):

请输入一个整数:abc

错误:输入的不是有效的整数!

运行示例 2(输入 0):

请输入一个整数:0

错误:除数不能为零!

运行示例 3(输入 5):

请输入一个整数:5

结果:2.0

12.3.2 一个 except 块处理多种异常

可以将多种异常类型放在一个元组中,用一个except块处理:

try:

num = int(input("请输入一个整数:"))

result = 10 / num

print("结果:", result)

except (ValueError, ZeroDivisionError):

print("错误:输入无效或除数为零!")

这种方式适合对多种异常进行相同处理的场景,但无法区分具体是哪种异常。

12.4 获取异常信息

在处理异常时,有时需要获取异常的详细信息(如错误原因),可以使用as关键字将异常对象赋值给一个变量。

try:

10 / 0

except ZeroDivisionError as e:

print("发生异常:", e) # 打印异常信息

print("异常类型:", type(e)) # 打印异常类型

运行结果:

发生异常:division by zero

异常类型:<class 'ZeroDivisionError'>

示例:处理文件打开异常并获取信息

try:

with open("nonexistent.txt", "r") as file:

content = file.read()

except FileNotFoundError as e:

print(f"文件操作错误:{e}")

运行结果:

文件操作错误:[Errno 2] No such file or directory: 'nonexistent.txt'

12.5 else 子句

try-except语句可以搭配else子句,else块中的代码会在try块没有发生异常时执行。

try:

num = int(input("请输入一个正数:"))

if num <= 0:

raise ValueError("输入的数不是正数") # 主动抛出异常(后面会讲解)

except ValueError as e:

print("错误:", e)

else:

# 只有当try块没有异常时,才会执行else块

print(f"你输入的正数是:{num}")

运行示例 1(输入负数):

请输入一个正数:-5

错误:输入的数不是正数

运行示例 2(输入正数):

请输入一个正数:10

你输入的正数是:10

else子句的作用是将 “可能发生异常的代码” 和 “正常执行的代码” 分开,使程序结构更清晰。

12.6 finally 子句

try-except语句还可以搭配finally子句,finally块中的代码无论是否发生异常都会执行,通常用于释放资源(如关闭文件、断开数据库连接等)。

try:

file = open("test.txt", "r")

content = file.read()

print("文件内容:", content)

except FileNotFoundError:

print("错误:文件不存在")

finally:

# 无论是否发生异常,都会执行finally块,确保文件关闭

if 'file' in locals() and not file.closed:

file.close()

print("文件已关闭")

运行示例 1(文件存在):

文件内容:Hello, World!

文件已关闭

运行示例 2(文件不存在):

错误:文件不存在

文件已关闭

在实际开发中,finally常用来处理必须执行的清理操作,即使程序发生异常也不会遗漏。

12.7 主动抛出异常(raise 语句)

除了处理程序运行中自动产生的异常,还可以使用raise语句主动抛出异常,用于在满足特定条件时告知程序发生了错误。

语法如下:

raise 异常类型(异常信息)

示例:判断年龄是否合法

def check_age(age):

if not isinstance(age, int):

# 主动抛出TypeError异常

raise TypeError("年龄必须是整数")

if age < 0 or age > 150:

# 主动抛出ValueError异常

raise ValueError("年龄必须在0到150之间")

print(f"年龄{age}是合法的")

try:

check_age(200)

except (TypeError, ValueError) as e:

print("错误:", e)

运行结果:

错误:年龄必须在0到150之间

主动抛出异常可以使函数或方法的错误处理更明确,让调用者知道需要处理哪些可能的错误。

12.8 自定义异常

Python 允许定义自己的异常类,即自定义异常,用于表示特定业务场景下的错误。自定义异常需要继承自Exception类(或其子类)。

示例:定义一个表示余额不足的异常

# 自定义异常类,继承自Exception

class InsufficientFundsError(Exception):

"""表示账户余额不足的异常"""

def __init__(self, balance, amount):

self.balance = balance # 当前余额

self.amount = amount # 尝试支出的金额

super().__init__(f"余额不足:当前余额{balance},尝试支出{amount}")

# 使用自定义异常

def withdraw(balance, amount):

if amount > balance:

# 抛出自定义异常

raise InsufficientFundsError(balance, amount)

return balance - amount

try:

new_balance = withdraw(100, 150)

print(f"取款成功,新余额:{new_balance}")

except InsufficientFundsError as e:

print("取款失败:", e)

运行结果:

取款失败:余额不足:当前余额100,尝试支出150

自定义异常可以使异常信息更贴合具体业务,提高代码的可读性和可维护性。

12.9 示例:异常处理的综合应用

实现一个简易的计算器,支持加、减、乘、除运算,并处理各种可能的异常(如输入非数字、除数为零等)。

def calculator():

print("简易计算器(支持 + - * /)")

try:

# 获取用户输入并转换为数字

num1 = float(input("请输入第一个数字:"))

operator = input("请输入运算符(+ - * /):")

num2 = float(input("请输入第二个数字:"))

# 执行计算

if operator == "+":

result = num1 + num2

elif operator == "-":

result = num1 - num2

elif operator == "*":

result = num1 * num2

elif operator == "/":

if num2 == 0:

# 主动抛出除数为零的异常

raise ZeroDivisionError("除数不能为零")

result = num1 / num2

else:

# 主动抛出不支持的运算符异常

raise ValueError(f"不支持的运算符:{operator}")

print(f"结果:{num1} {operator} {num2} = {result}")

except ValueError as e:

print(f"输入错误:{e}")

except ZeroDivisionError as e:

print(f"计算错误:{e}")

except Exception as e:

# 捕获其他未预料到的异常

print(f"发生未知错误:{e}")

else:

print("计算完成!")

finally:

print("计算器会话结束。\n")

# 运行计算器

calculator()

运行示例 1(正常计算):

简易计算器(支持 + - * /)

请输入第一个数字:10

请输入运算符(+ - * /):*

请输入第二个数字:5

结果:10.0 * 5.0 = 50.0

计算完成!

计算器会话结束。

运行示例 2(输入非数字):

简易计算器(支持 + - * /)

请输入第一个数字:abc

输入错误:could not convert string to float: 'abc'

计算器会话结束。

运行示例 3(除数为零):

简易计算器(支持 + - * /)

请输入第一个数字:10

请输入运算符(+ - * /):/

请输入第二个数字:0

计算错误:除数不能为零

计算器会话结束。

12.10 小结

本章我们学习了 Python 中的异常处理,包括异常的概念、try-except语句的基本用法、捕获多种异常、获取异常信息,以及else和finally子句的作用。此外,还学习了如何使用raise语句主动抛出异常和定义自定义异常。

异常处理是编写健壮程序的关键技术,它可以帮助我们捕获和处理程序运行中可能出现的错误,避免程序意外崩溃。在实际开发中,应根据具体场景合理使用异常处理,既不能忽略可能的异常,也不要过度捕获异常(掩盖真正的错误)。

下一章,我们将学习 Python 中的模块和包,了解如何组织和重用代码。

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接