一、什么是异常(Exception)?
异常是指程序运行过程中出现的错误情况。比如:
- 打开一个不存在的文件
- 0作为除数
- 列表索引越界
- 类型转换失败
二、基本结构:try...except
try:
# 可能出错的代码
except 错误类型:
# 出错时执行的代码
示例:
try:
x = 10 / 0 # 除零错误
except ZeroDivisionError:
print("不能除以0")
输出:
不能除以0
三、完整结构详解
try:
# 尝试执行的代码块
except 错误类型1:
# 捕获错误类型1后的处理
except 错误类型2:
# 捕获错误类型2后的处理
else:
# 没有异常时执行
finally:
# 无论是否有异常都执行(如关闭文件/资源)
示例:
try:
num = int(input("请输入一个整数:"))
result = 10 / num
except ValueError:
print("请输入有效的整数")
except ZeroDivisionError:
print("不能输入0")
else:
print("结果是:",result)
finally:
print("程序结束")
四、常见异常类型及用途
异常类型 | 触发场景 |
ZeroDivisionError | 除以零 |
ValueError | 类型转换失败,如 int("abc") |
IndexError | 索引超出列表范围 |
KeyError | 字典中访问不存在的键 |
FileNotFoundError | 打开一个不存在的文件 |
TypeError | 操作类型不兼容 |
五、常见实用技巧和场景
1.捕获多个异常
try:
a = int("abc")
b = 10 /0
except (ValueError,ZeroDivisionError) as e:
print("出错啦",e)
2.不确定错误类型,先写Exception
try:
# 复杂逻辑
do_something()
except Exception as e:
print("出现未知错误",e)
注意:不要滥用Exception,否则可能掩盖真正的bug
3.使用finally清理资源
try:
file = open("data.txt","r")
content = file.read()
except FileNotFound:
print("文件未找到")
finally:
file.close()
print("文件关闭")
4.自定义函数内使用try-except
def safe_divide(x,y):
try:
return x/y
ecxept ZeroDivisionError:
return "不能除以0"
print(safe_divide(10,0)) #输出:不能除以0
六、自定义异常类(Custom Exceptions)
有时候内置异常不能准确表达业务逻辑,此时可以自定义异常类
语法:
class 自定义异常名(Exception):
pass
示例:
# 定义一个自定义异常类,继承自内置的Exception类
class PasswordTooShortError(Exception):
"""密码长度太短的异常"""
pass
# 定义一个检查密码的函数
def check_password(pwd):
#如果密码长度小于6,就主动抛出自定义异常
if len(pwd)<6:
raise PasswordTooShortError("密码长度不能少于6位")
# 使用try-except捕获自定义异常
try:
check_password("abc")
except PasswordTooShortError as e:
#捕获到自定义异常后,打印错误信息
print("发生错误:",e)
七、使用raise主动抛出异常
raise可以手动触发异常,让函数调用者知道出错了
基本用法:
raise 异常类型("错误信息")
示例:
# 定义一个除法函数,带参数检查
def divide(x,y):
# 如果除数是0,就主动抛出除零异常
if y == 0:
rasie ZeroDivisionError("除数不能为0")
# 否则返回除法结果
return x/y
# 使用try-except 捕获异常
try:
result = divide(10,0)
except ZeroDivisionError as e: #重命名异常,以便于后续再输出错误信息
print("错误",e)
八、异常链(raise...from...)
在某些场景中,一个异常是由另一个异常引起的,为了因果链,可以使用:
raise 新异常 from 原始异常
示例:
# 定义一个读取配置文件的函数
def read_config(path):
try:
# 试图打开并读取文件内容
with open(path) as f:
return f.read()
except FileNotFoundError as e:
# 如果文件找不到,抛出新的RuntimeError,并保留原始异常信息
raise RuntimeError("配置文件读取失败") from e
# 使用try-except捕获RuntimeError
try:
read_config("no_such_file.cfg") #尝试读取一个不存在的文件
except RuntimeError as e:
#打印新的异常信息
print("RuntimeError:",e)
#打印原始异常的详细原因(通过异常链追踪)
print("原始原因:",e.__casuse__)
九、高级技巧总结表
技巧 | 说明 | 示例代码 |
自定义异常类 | 用于表达特定业务逻辑错误 | class MyError(Exception):.. |
raise抛出异常 | 控制程序流,校验参数 | raise ValueError("不合法") |
raise from原始异常 | 保留原始异常上下文 | raise NewError from old_error |
异常嵌套处理 | 不同层次处理不同错误 | 外层用broad except,内层细分异常处理 |
异常日志记录 | 结合logging模块记录错误信息 | logging.exception(e) |