当前位置: 首页 > news >正文

[Python编程] Python3 错误与异常

目录

一、Python3 错误的分类:先搞懂 “错在哪”

1️⃣语法错误:最基础的 “拼写错误”

常见场景与示例

关键特点

2️⃣运行时异常:“代码能跑,但中途出问题”

常见场景与示例

关键特点

二、Python3 常见异常类型:认识 “敌人” 才能应对

补充说明

三、Python3 异常的处理:让程序 “优雅容错”

1️⃣核心语法:try/except 基础用法

基本语法结构

示例 1:捕获特定异常(推荐)

示例 2:捕获多个异常

      示例 3:通用异常捕获(谨慎使用)

2️⃣进阶用法:try/except/else

语法结构

示例:文件读取场景

3️⃣必学用法:try/except/finally

语法结构

示例:确保文件关闭

4️⃣简化资源管理:with 关键字

核心原

示例 1:简化文件操作

示例 2:其他资源管理场景

5️⃣主动触发异常:raise 语句

基本语法

示例 1:主动触发异常

示例 2:重新抛出异常

四、Python3 自定义异常:处理 “业务专属错误”

1️⃣自定义异常的规则

2️⃣示例 1:简单自定义异常

3️⃣示例 2:复杂场景(多自定义异常)

五、Python3 assert(断言):提前 “排查隐患”

1️⃣基本语法

2️⃣示例 1:环境检查

3️⃣示例 2:参数校验

4️⃣注意事项

六、总结:异常处理的 “最佳实践”


对于 Python 初学者来说,代码运行时遇到报错往往会手足无措。其实,错误和异常并非 “洪水猛兽”,而是程序在 “提醒” 我们哪里需要优化。掌握错误与异常的处理方法,是写出健壮、可靠 Python 代码的关键一步。

一、Python3 错误的分类:先搞懂 “错在哪”

在 Python3 中,程序运行出现的问题主要分为两类:语法错误和运行时异常。二者的本质区别在于:语法错误是 “代码写得不对”,程序根本无法启动;运行时异常是 “代码语法没问题,但执行中出了意外”,程序能启动但会中途报错。

1️⃣语法错误:最基础的 “拼写错误”

语法错误又称 “解析错误”,是初学者最常踩的坑 —— 本质是代码违反了 Python 的语法规则,导致解释器无法识别和执行。

常见场景与示例

比如少写冒号、括号不匹配、缩进错误等:

python

# 错误示例:while 循环后少写冒号,print 函数括号不完整
while True print("Hello world')

运行后会出现如下报错,解释器会贴心地用箭头指出错误位置:

plaintext

File "<stdin>", line 1while True print("Hello world')^
SyntaxError: invalid syntax  # 语法错误:无效语法
关键特点
  • 语法错误会直接阻断程序运行,解释器无法继续解析代码;
  • 必须修改代码中的语法问题(如补全冒号、修正括号),程序才能正常启动;
  • 常见的语法错误还包括 IndentationError(缩进错误),比如 Tab 和空格混合使用导致的 TabError

2️⃣运行时异常:“代码能跑,但中途出问题”

即使代码语法完全正确,执行过程中也可能因为 “逻辑漏洞” 或 “外部条件不满足” 触发错误,这就是运行时异常。与语法错误不同,异常是可以被程序 “捕获并处理” 的,避免程序直接崩溃。

常见场景与示例

最典型的例子是 “除数为零”—— 语法上没问题,但数学逻辑不允许:

python

# 代码语法正确,但执行时会触发异常
print(1 / 0)

运行后会出现 “异常追踪信息”,明确指出异常类型和位置:

plaintext

Traceback (most recent call last):File "d:\py3\hello.py", line 1, in <module>print(1 / 0)
ZeroDivisionError: division by zero  # 异常类型:除数为零
关键特点
  • 程序能正常启动,但执行到特定代码行时触发异常;
  • 异常信息会显示 “异常类型”(如 ZeroDivisionError)和 “错误位置”,便于定位问题;
  • 通过后续的 “异常处理机制”,可以捕获这些异常,让程序继续运行(比如提示 “除数不能为零”,而不是直接崩溃)。

二、Python3 常见异常类型:认识 “敌人” 才能应对

Python 内置了数十种异常类型,每种类型对应特定的错误场景。初学者无需死记硬背,但要熟悉最常用的几种,方便快速定位问题。以下是按 “使用频率” 排序的核心异常类型:

异常类型触发场景说明示例
ZeroDivisionError除法运算中,除数为 01 / 0
TypeError操作或函数应用于 “不适当类型” 的对象1 + "2"(整数和字符串无法相加)
ValueError函数参数 “类型正确但值无效”int("abc")(字符串是文本,无法转整数)
IndexError访问序列(列表、字符串等)时,索引超出范围lst = [1,2]; lst[3]
KeyError访问字典时,键(key)不存在dict = {"a":1}; dict["b"]
AttributeError访问对象的属性或方法时,对象没有该属性 / 方法s = "hello"; s.append("!")(字符串无 append 方法)
FileNotFoundError尝试打开不存在的文件(属于 OSError 的子类)open("不存在的文件.txt")
NameError使用未定义的变量或函数名print(undefined_var)
AssertionError断言语句(assert)的条件为 Falseassert 1 == 2
KeyboardInterrupt用户手动中断程序(如按 Ctrl+C运行程序时按 Ctrl+C
补充说明
  • 所有异常的 “祖宗” 是 BaseException,但我们常用的异常(如上述所有类型)都继承自 ExceptionBaseException 的子类);
  • 异常类型的命名有规律:大多以 “Error” 结尾,便于识别(如 ZeroDivisionErrorTypeError)。

三、Python3 异常的处理:让程序 “优雅容错”

遇到异常时,默认行为是 “程序崩溃并打印异常信息”。但通过 try/except 等语句,我们可以 “捕获异常” 并执行自定义逻辑(如提示用户、记录日志),让程序继续运行 —— 这就是 “异常处理”。

1️⃣核心语法:try/except 基础用法

try/except 是异常处理的核心结构,逻辑是:“尝试执行一段代码,如果出异常就处理,没异常就正常执行”。

基本语法结构

python

try:# 尝试执行的代码(可能触发异常的代码)可能出错的代码块
except [异常类型1, 异常类型2, ...] as 异常变量:# 若触发指定类型的异常,执行这里的代码异常处理逻辑(如提示、日志)
  • 示例 1:捕获特定异常(推荐)

      明确捕获 “除数为零” 异常,避免程序崩溃:

      python

try:result = 1 / 0  # 可能触发 ZeroDivisionError
except ZeroDivisionError as e:# 打印自定义提示,同时显示异常信息print(f"出错了!原因:{e}")  # 输出:出错了!原因:division by zero
  • 示例 2:捕获多个异常

      如果一段代码可能触发多种异常,可以用元组指定多个异常类型:

      python

try:# 可能触发 TypeError(如 1+"2")或 ZeroDivisionError(如 1/0)num = int(input("请输入一个数字:"))result = 10 / num
except (TypeError, ZeroDivisionError) as e:print(f"输入无效或除数为零!原因:{e}")
      示例 3:通用异常捕获(谨慎使用)

如果不确定会触发什么异常,可以用 Exception(所有常规异常的基类)捕获所有异常。但不建议滥用 —— 会掩盖未知错误,不利于调试:

python

try:num = int(input("请输入一个数字:"))result = 10 / num
except Exception as e:print(f"发生未知错误!原因:{e}")

2️⃣进阶用法:try/except/else

else 子句是 “可选的”,作用是:当 try 中的代码 “没有触发任何异常” 时,执行 else 中的逻辑。

语法结构

python

try:可能出错的代码块
except 异常类型 as e:异常处理逻辑
else:# 只有 try 中无异常时,才执行这里无异常时的逻辑
示例:文件读取场景

判断文件是否能正常打开,若打开成功则读取内容(避免将 “读取文件” 的逻辑放入 try 中,减少不必要的异常捕获):

python

import sys# 从命令行参数获取文件名
for filename in sys.argv[1:]:try:# 尝试打开文件(可能触发 FileNotFoundError)f = open(filename, 'r')except FileNotFoundError as e:print(f"无法打开文件:{filename},原因:{e}")else:# 打开成功,读取文件行数并打印lines = f.readlines()print(f"{filename} 有 {len(lines)} 行内容")f.close()  # 记得关闭文件

3️⃣必学用法:try/except/finally

finally 子句是 “可选的”,但极其重要 ——无论 try 中是否触发异常,finally 中的代码 “一定会执行”。常用于 “释放资源”(如关闭文件、断开数据库连接)。

语法结构

python

try:可能出错的代码块
except 异常类型 as e:异常处理逻辑
else:无异常时的逻辑
finally:# 无论是否有异常,都会执行这里资源释放逻辑(如关闭文件、断开连接)
  • 示例:确保文件关闭

即使读取文件时触发异常,finally 也会执行 f.close(),避免文件资源泄漏:

python

try:f = open("test.txt", 'r')content = f.read()print("文件内容:", content)
except FileNotFoundError as e:print(f"出错了:{e}")
finally:# 无论是否有异常,都关闭文件if 'f' in locals():  # 判断 f 是否已定义(避免未打开文件时报错)f.close()print("文件已关闭")

4️⃣简化资源管理:with 关键字

try/finally 虽然能确保资源释放,但代码略显繁琐。Python 提供了 with 关键字,它封装了 try/finally 的逻辑,能 “自动管理资源”(如自动关闭文件、自动断开连接),让代码更简洁。

  • 核心原理

with 语句依赖 “上下文管理器”(实现 __enter__ 和 __exit__ 方法的类):

  • 进入 with 块时,调用 __enter__ 方法(如打开文件);
  • 离开 with 块时(无论是否有异常),自动调用 __exit__ 方法(如关闭文件)。
  • 示例 1:简化文件操作

      用 with 打开文件,无需手动调用 close()—— 离开 with 块时会自动关闭:

      python

# 自动打开文件,离开 with 块时自动关闭
with open("test.txt", 'w') as f:f.write("Hello, Python!")  # 写入内容# 此时文件已自动关闭,无需手动 f.close()
  • 示例 2:其他资源管理场景

      with 不仅用于文件,还可用于数据库连接、线程锁等场景。例如用 with 管理数据库连接(需依赖具体数据库库):

python

import sqlite3# 自动连接数据库,离开 with 块时自动关闭连接
with sqlite3.connect('test.db') as conn:cursor = conn.cursor()cursor.execute("CREATE TABLE IF NOT EXISTS users (id INT, name TEXT)")conn.commit()

5️⃣主动触发异常:raise 语句

除了 “被动捕获异常”,我们还可以用 raise 语句 “主动触发异常”—— 常用于 “自定义业务规则校验”(如判断参数是否符合要求)。

基本语法

python

# 1. 触发指定类型的异常
raise 异常类型("异常描述信息")# 2. 重新抛出捕获的异常(不处理,交给上层处理)
try:代码块
except 异常类型 as e:# 打印日志后,重新抛出异常print(f"捕获到异常:{e}")raise  # 重新抛出当前异常
  • 示例 1:主动触发异常

      判断参数 x 是否大于 5,若大于则触发 Exception 并提示:

      python

x = 10
if x > 5:# 主动触发异常,描述信息会显示在报错中raise Exception(f"x 不能大于 5,当前 x 的值为:{x}")

运行后报错:

plaintext

Traceback (most recent call last):File "d:\py3\test.py", line 3, in <module>raise Exception(f"x 不能大于 5,当前 x 的值为:{x}")
Exception: x 不能大于 5,当前 x 的值为:10
  • 示例 2:重新抛出异常

      捕获异常后不处理,而是交给上层代码处理(比如在日志记录后,让调用者处理异常):

      python

def calculate(x):try:if x == 0:raise ZeroDivisionError("x 不能为 0")return 10 / xexcept ZeroDivisionError as e:# 记录日志后,重新抛出异常print(f"日志:捕获到异常:{e}")raise  # 重新抛出,让调用者处理# 调用函数,处理重新抛出的异常
try:calculate(0)
except ZeroDivisionError as e:print(f"调用者处理异常:{e}")

运行结果:

plaintext

日志:捕获到异常:x 不能为 0
调用者处理异常:x 不能为 0

四、Python3 自定义异常:处理 “业务专属错误”

Python 内置的异常类型能覆盖大多数通用场景,但在实际开发中,我们可能需要 “自定义异常” 来描述 “业务专属的错误”(如 “用户余额不足”“订单状态无效”)。

1️⃣自定义异常的规则

  • 自定义异常类必须继承自 Exception(或其子类),不能直接继承 BaseException(避免捕获系统级异常,如 KeyboardInterrupt);
  • 异常类的命名建议以 “Error” 结尾,符合 Python 命名规范;
  • 可以重写 __init__ 方法(初始化异常信息)和 __str__ 方法(自定义异常的字符串描述)。

2️⃣示例 1:简单自定义异常

      定义一个 “余额不足异常”,用于处理用户支付时的余额问题:

      python

# 自定义异常类,继承自 Exception
class InsufficientBalanceError(Exception):# 重写 __init__ 方法,接收余额和所需金额def __init__(self, current_balance, required_amount):self.current_balance = current_balanceself.required_amount = required_amount# 重写 __str__ 方法,自定义异常描述def __str__(self):return f"余额不足!当前余额:{self.current_balance},所需金额:{self.required_amount}"# 模拟支付函数
def pay(amount):current_balance = 100  # 假设用户当前余额为 100if amount > current_balance:# 主动触发自定义异常raise InsufficientBalanceError(current_balance, amount)print(f"支付成功!支付金额:{amount},剩余余额:{current_balance - amount}")# 测试:捕获自定义异常
try:pay(150)  # 所需金额 150 > 余额 100,触发异常
except InsufficientBalanceError as e:print(f"支付失败:{e}")  # 输出:支付失败:余额不足!当前余额:100,所需金额:150

3️⃣示例 2:复杂场景(多自定义异常)

当一个模块需要多种异常时,建议先定义一个 “基础异常类”,再基于它定义多个 “子类异常”—— 便于统一管理和捕获。

例如,定义一个 “订单相关的基础异常”,再衍生 “订单不存在”“订单已取消” 两种异常:

python

# 订单相关的基础异常类
class OrderError(Exception):pass# 子类1:订单不存在异常
class OrderNotFoundError(OrderError):def __str__(self):return f"订单 {self.order_id} 不存在"def __init__(self, order_id):self.order_id = order_id# 子类2:订单已取消异常
class OrderCancelledError(OrderError):def __str__(self):return f"订单 {self.order_id} 已取消,无法操作"def __init__(self, order_id):self.order_id = order_id# 模拟获取订单状态的函数
def get_order_status(order_id):# 模拟订单数据:key 是订单ID,value 是状态("exists"/"cancelled"/"not_found")orders = {"1001": "exists", "1002": "cancelled"}if order_id not in orders:raise OrderNotFoundError(order_id)if orders[order_id] == "cancelled":raise OrderCancelledError(order_id)return f"订单 {order_id} 状态正常"# 测试:捕获多个自定义异常
try:print(get_order_status("1003"))  # 订单不存在
except OrderNotFoundError as e:print(f"错误:{e}")  # 输出:错误:订单 1003 不存在
except OrderCancelledError as e:print(f"错误:{e}")

五、Python3 assert(断言):提前 “排查隐患”

assert(断言)是 Python 提供的一种 “调试工具”,用于在代码中 “提前判断条件是否满足”—— 如果条件为 False,则触发 AssertionError 异常,直接终止程序;如果条件为 True,则不影响程序运行。

1️⃣基本语法

python

# 语法1:仅判断条件,无自定义提示
assert 条件表达式# 语法2:条件为 False 时,显示自定义提示
assert 条件表达式, "条件不满足时的提示信息"

等价于以下逻辑(但 assert 更简洁):

python

if not 条件表达式:raise AssertionError("条件不满足时的提示信息")

2️⃣示例 1:环境检查

确保代码只在 Linux 系统下运行,否则提前报错(避免程序运行后出现兼容性问题):

python

import sys# 检查当前系统是否为 Linux(sys.platform 返回系统标识,如 "linux"、"win32")
assert "linux" in sys.platform, "该代码只能在 Linux 系统下执行!"# 如果条件满足,才执行后续代码
print("当前系统是 Linux,开始执行程序...")

若在 Windows 系统运行,会报错:

plaintext

AssertionError: 该代码只能在 Linux 系统下执行!

3️⃣示例 2:参数校验

在函数中用 assert 校验参数是否符合要求(如参数必须为正数):

python

运行

def calculate_square_root(num):# 断言:num 必须大于等于 0(否则无法计算平方根)assert num >= 0, f"参数必须为非负数,当前参数:{num}"return num ** 0.5# 测试
print(calculate_square_root(4))  # 条件满足,输出 2.0
print(calculate_square_root(-4)) # 条件不满足,触发 AssertionError

运行后报错:

plaintext

AssertionError: 参数必须为非负数,当前参数:-4

4️⃣注意事项

  • assert 主要用于 “调试阶段”,不能替代 if 判断或异常处理 —— 生产环境中,Python 解释器可能通过 -O 选项(优化模式)禁用 assert,导致断言失效;
  • 不要用 assert 处理 “预期内的错误”(如用户输入无效),应用 if 判断或 raise 异常;
  • assert 的核心作用是 “提前暴露程序中的逻辑漏洞”(如 “这里的参数不可能为负”),便于调试。

六、总结:异常处理的 “最佳实践”

  1. 优先捕获特定异常:避免用 Exception 捕获所有异常,防止掩盖未知错误;
  2. 用 finally 或 with 管理资源:确保文件、数据库连接等资源被正确释放,避免泄漏;
  3. 自定义异常要规范:继承 Exception,命名以 “Error” 结尾,复杂场景用 “基础类 + 子类”;
  4. assert 仅用于调试:不依赖 assert 处理业务逻辑,生产环境禁用 assert
  5. 异常信息要清晰:在 raise 或 except 中添加详细的描述信息(如参数值、文件名),便于定位问题。
http://www.dtcms.com/a/414432.html

相关文章:

  • 动态代理 java原生 vs Cglib
  • MQTT协议基础知识速成(智能家居项目)
  • 北京网站建设认知网络推广公司服务内容
  • 爬虫疑难问题解决方案整理
  • 如何制作PDF文件目录?
  • 左右翻网站模版网页美工设计教程
  • 牛客小白月赛121
  • 深入理解目标文件:从ELF格式到链接核心
  • Java系列知识之 ~ Spring 与 Spring Boot 常用注解对比说明
  • 郫县建设局网站wordpress如何运行
  • LeetCode 114.二叉树展开为链表
  • 机器人中的电机与扭矩入门
  • 站长平台如何推广自己的网站怎么做网页版网站
  • 深入理解BFC:解决margin折叠和浮动高度塌陷的利器
  • Spec Kit - 规范驱动开发工具包
  • 具有价值的常州做网站免费进销存软件哪个简单好用
  • creo二次开发seo职位信息
  • Windows 10 环境下 Redis 编译与运行指南
  • 【编号206】房地产统计年鉴2002~2023
  • 某大型广告公司实习感受
  • 【Day 68】Zabbix-自动监控-Web检测-分布式监控
  • 企业网站建设公司公司网站开发客户挖掘
  • 天拓四方集团IOT平台:赋能电气设备制造商数智化转型新引擎
  • 【STM32项目开源】基于STM32的智能鱼缸养殖系统
  • 【小迪安全v2023】学习笔记集合 --- 持续更新
  • Django - DRF
  • Python全方位处理XML指南:解析、修改与重写实战
  • LabVIEW实现B样条曲线拟合
  • 门户网站系统建设招标文件中国建设教育协会网站培训中心
  • 常熟网站网站建设在线教育自助网站建设平台