Python3 错误与异常完全指南
编程小白的全方位理解手册
本指南将用大白话解释Python中的错误和异常处理,涵盖从基本概念到高级技巧的所有内容。
即使你刚入门编程,也能轻松理解这些重要概念!
🚨 错误类型
1. 语法错误(SyntaxError)
代码不符合Python语法规则,程序根本无法运行
常见情况:
- 忘记写冒号
if x > 5
❌ (缺少:
) - 括号不匹配
print('hello'
❌ (缺少)
) - 错误的关键字拼写
whille True:
❌
2. 异常(Exception)
程序可以运行,但在执行过程中遇到问题而终止
关键区别:语法错误是代码还没运行就发现的错误,异常是代码运行过程中出现的问题。
常见内置异常
NameError
– 使用了未定义的变量TypeError
– 操作或函数应用于不适当类型的对象ValueError
– 操作或函数接收到类型正确但值不合适的参数IndexError
– 序列索引超出范围KeyError
– 字典中查找不存在的键ZeroDivisionError
– 除以零FileNotFoundError
– 请求的文件不存在
🛡️ 异常处理
1. try-except 基本结构
尝试执行代码,如果出现异常则执行except部分
try:
# 尝试执行的代码
result = 10 / 0
except ZeroDivisionError:
# 处理异常的代码
print(“不能除以零!”)
# 尝试执行的代码
result = 10 / 0
except ZeroDivisionError:
# 处理异常的代码
print(“不能除以零!”)
2. 多个except块
处理不同类型的异常
try:
# 可能出错的代码
except TypeError:
print(“类型错误!”)
except ValueError:
print(“数值错误!”)
except Exception as e:
print(f”其他错误: {e}”)
# 可能出错的代码
except TypeError:
print(“类型错误!”)
except ValueError:
print(“数值错误!”)
except Exception as e:
print(f”其他错误: {e}”)
提示: Exception
是所有内置异常的基类,放在最后可以捕获所有未处理的异常。
3. try-except-else
当try块中没有异常时执行else块
try:
result = 10 / 2
except ZeroDivisionError:
print(“除零错误”)
else:
# 只有在没有异常时才会执行
print(“计算结果:”, result)
result = 10 / 2
except ZeroDivisionError:
print(“除零错误”)
else:
# 只有在没有异常时才会执行
print(“计算结果:”, result)
4. try-finally
无论是否发生异常都会执行finally块
try:
file = open(‘test.txt’, ‘r’)
# 文件操作…
except FileNotFoundError:
print(“文件未找到”)
finally:
# 无论是否发生异常都会执行
file.close()
print(“文件已关闭”)
file = open(‘test.txt’, ‘r’)
# 文件操作…
except FileNotFoundError:
print(“文件未找到”)
finally:
# 无论是否发生异常都会执行
file.close()
print(“文件已关闭”)
✨ 高级技巧
1. 自定义异常
创建自己的异常类型,使错误处理更清晰
class NegativeNumberError(Exception):
pass # 创建一个简单的自定义异常
def check_positive(num):
if num < 0:
raise NegativeNumberError(“数值不能为负数!”)
return num
try:
check_positive(-5)
except NegativeNumberError as e:
print(e) # 输出: 数值不能为负数!
pass # 创建一个简单的自定义异常
def check_positive(num):
if num < 0:
raise NegativeNumberError(“数值不能为负数!”)
return num
try:
check_positive(-5)
except NegativeNumberError as e:
print(e) # 输出: 数值不能为负数!
2. 异常链
在处理一个异常时抛出另一个异常,同时保留原始异常信息
try:
10 / 0
except ZeroDivisionError as e:
raise ValueError(“处理除法时出错”) from e
10 / 0
except ZeroDivisionError as e:
raise ValueError(“处理除法时出错”) from e
3. 断言(assert)
用于调试,检查条件是否为真,如果为假则抛出AssertionError
def divide(a, b):
# 断言b不为0
assert b != 0, “除数不能为零”
return a / b
print(divide(10, 2)) # 正常执行
print(divide(10, 0)) # 抛出AssertionError: 除数不能为零
# 断言b不为0
assert b != 0, “除数不能为零”
return a / b
print(divide(10, 2)) # 正常执行
print(divide(10, 0)) # 抛出AssertionError: 除数不能为零
最佳实践:
- 不要用assert做数据验证,仅用于调试
- 生产环境可通过
-O
选项禁用断言
4. 上下管理器(with语句)
简化资源管理,自动处理清理工作
with open(‘file.txt’, ‘r’) as file:
data = file.read()
# 文件会自动关闭,无需手动调用file.close()
data = file.read()
# 文件会自动关闭,无需手动调用file.close()
等同于:
try:
file = open(‘file.txt’, ‘r’)
data = file.read()
finally:
file.close() # 确保文件总是被关闭
file = open(‘file.txt’, ‘r’)
data = file.read()
finally:
file.close() # 确保文件总是被关闭
🏆 最佳实践
异常处理原则
“请求宽恕比请求许可更容易” (Easier to Ask Forgiveness than Permission – EAFP)
Python推荐尝试执行操作并处理异常,而不是先检查再执行
EAFP vs LBYL
# EAFP 风格 (Pythonic)
try:
value = my_dict[‘key’]
except KeyError:
# 处理键不存在的情况
# LBYL 风格 (Look Before You Leap)
if ‘key’ in my_dict:
value = my_dict[‘key’]
else:
# 处理键不存在的情况
try:
value = my_dict[‘key’]
except KeyError:
# 处理键不存在的情况
# LBYL 风格 (Look Before You Leap)
if ‘key’ in my_dict:
value = my_dict[‘key’]
else:
# 处理键不存在的情况
异常处理注意事项
- 避免空的except块(会捕获所有异常,包括系统退出)
- 尽量具体地捕获异常(不要过度使用except Exception)
- 不要用异常处理做流程控制(会降低性能)
- 清理资源使用finally或with语句
- 在异常信息中包含有用信息
何时使用异常处理:
- 处理外部资源(文件、网络、数据库)
- 处理用户输入验证
- 处理预料中的异常情况(如文件不存在)
- 在深层嵌套中处理错误
错误示例:
while True:
try:
num = int(input(“请输入数字: “))
break
except: # 太宽泛,会捕获所有异常
print(“输入无效,请重试”)
try:
num = int(input(“请输入数字: “))
break
except: # 太宽泛,会捕获所有异常
print(“输入无效,请重试”)
改进后:
while True:
try:
num = int(input(“请输入数字: “))
break
except ValueError: # 只捕获数值转换错误
print(“输入无效,请输入数字”)
try:
num = int(input(“请输入数字: “))
break
except ValueError: # 只捕获数值转换错误
print(“输入无效,请输入数字”)