Python 异常处理
异常是程序执行过程中发生的错误。Python提供了强大的异常处理机制,让我们能够优雅地处理错误情况,防止程序崩溃。
什么是异常?
当Python检测到错误时,会引发异常。如果没有处理异常,程序将会终止并显示错误信息。
python
# 这将引发ZeroDivisionError异常
# print(10 / 0)
# 这将引发ValueError异常
# int("abc")
try...except 语句
基本的异常处理结构是try...except语句:
python
try:
# 可能出现异常的代码
result = 10 / 0
except:
# 处理异常的代码
print("发生了错误")
捕获特定异常
可以捕获特定类型的异常:
python
try:
x = int(input("请输入一个数字: "))
y = 10 / x
print(f"结果是: {y}")
except ValueError:
print("输入的不是有效数字")
except ZeroDivisionError:
print("不能除以零")
使用as关键字获取异常信息
python
try:
x = int(input("请输入一个数字: "))
y = 10 / x
except ValueError as e:
print(f"值错误: {e}")
except ZeroDivisionError as e:
print(f"除零错误: {e}")
else 子句
else子句在没有异常发生时执行:
python
try:
x = int(input("请输入一个数字: "))
y = 10 / x
except ValueError:
print("输入的不是有效数字")
except ZeroDivisionError:
print("不能除以零")
else:
print(f"结果是: {y}")
finally 子句
finally子句无论是否发生异常都会执行:
python
try:
file = open("example.txt", "r")
content = file.read()
print(content)
except FileNotFoundError:
print("文件未找到")
finally:
try:
file.close()
print("文件已关闭")
except:
print("无法关闭文件")
抛出异常
使用raise语句可以手动抛出异常:
python
def check_age(age):
if age < 0:
raise ValueError("年龄不能为负数")
elif age > 150:
raise ValueError("年龄不能超过150")
else:
print(f"年龄 {age} 是有效的")
try:
check_age(-5)
except ValueError as e:
print(f"错误: {e}")
自定义异常
可以通过继承Exception类创建自定义异常:
python
class CustomError(Exception):
"""自定义异常类"""
def __init__(self, message):
self.message = message
super().__init__(self.message)
class AgeError(Exception):
"""年龄相关异常"""
pass
def validate_age(age):
if age < 0:
raise AgeError("年龄不能为负数")
elif age > 150:
raise AgeError("年龄不能超过150")
try:
validate_age(200)
except AgeError as e:
print(f"年龄验证错误: {e}")
常见异常示例
python
# IndexError - 列表索引超出范围
try:
my_list = [1, 2, 3]
print(my_list[5])
except IndexError as e:
print(f"索引错误: {e}")
# KeyError - 字典键不存在
try:
my_dict = {"a": 1, "b": 2}
print(my_dict["c"])
except KeyError as e:
print(f"键错误: {e}")
# AttributeError - 属性不存在
try:
my_string = "hello"
my_string.append("world")
except AttributeError as e:
print(f"属性错误: {e}")
# TypeError - 类型错误
try:
result = "5" + 5
except TypeError as e:
print(f"类型错误: {e}")
# FileNotFoundError - 文件未找到
try:
with open("nonexistent.txt", "r") as file:
content = file.read()
except FileNotFoundError as e:
print(f"文件未找到错误: {e}")
多个异常处理
可以在一个except子句中处理多种异常:
python
try:
x = int(input("请输入一个数字: "))
result = 10 / x
my_list = [1, 2, 3]
print(my_list[x])
except (ValueError, ZeroDivisionError, IndexError) as e:
print(f"发生了以下错误之一: {type(e).__name__}: {e}")
异常链
可以将一个异常作为另一个异常的原因:
python
def process_data(data):
try:
return int(data)
except ValueError as e:
raise TypeError("数据处理失败") from e
try:
process_data("abc")
except TypeError as e:
print(f"类型错误: {e}")
print(f"原因: {e.__cause__}")
上下文管理器和with语句
许多资源管理场景可以使用with语句自动处理异常:
python
# 文件操作中的异常处理
try:
with open("example.txt", "r") as file:
content = file.read()
# 即使发生异常,文件也会自动关闭
result = 10 / 0 # 这会引发异常
except FileNotFoundError:
print("文件未找到")
except ZeroDivisionError:
print("除零错误")
# 文件在此处已经自动关闭
断言
assert语句用于调试,如果条件为假则引发AssertionError:
python
def divide(x, y):
assert y != 0, "除数不能为零"
return x / y
try:
result = divide(10, 0)
except AssertionError as e:
print(f"断言错误: {e}")
日志记录与异常
结合日志记录可以更好地追踪异常:
python
import logging
# 配置日志
logging.basicConfig(level=logging.ERROR)
def divide_numbers(x, y):
try:
result = x / y
return result
except ZeroDivisionError as e:
logging.error(f"除零错误: {e}")
return None
except Exception as e:
logging.error(f"未知错误: {e}")
return None
result = divide_numbers(10, 0)
最佳实践
- 具体异常优于通用异常:捕获具体的异常类型而不是使用裸露的except
- 不要忽略异常:即使不需要处理异常也不要空的except块
- 使用finally清理资源:确保重要资源得到释放
- 记录异常信息:使用日志记录异常以便调试
- 自定义异常要有意义:创建能够清楚表达业务逻辑的异常类
- 异常处理不应影响正常流程:异常处理代码应该是辅助性的
实际应用示例
网络请求异常处理
python
import urllib.request
import urllib.error
def fetch_url(url):
try:
response = urllib.request.urlopen(url)
return response.read()
except urllib.error.HTTPError as e:
print(f"HTTP错误: {e.code} {e.reason}")
except urllib.error.URLError as e:
print(f"URL错误: {e.reason}")
except Exception as e:
print(f"未知错误: {e}")
return None
# content = fetch_url("https://www.example.com")
数据库操作异常处理
python
# 示例伪代码
def database_operation():
connection = None
try:
# connection = connect_to_database()
# result = execute_query(connection, "SELECT * FROM users")
pass
except ConnectionError as e:
print(f"数据库连接错误: {e}")
except SQLSyntaxError as e:
print(f"SQL语法错误: {e}")
finally:
if connection:
# connection.close()
pass
结论
异常处理是编写健壮Python程序的关键部分。通过合理使用try、except、else和finally语句,我们可以创建能够优雅处理错误情况的应用程序。良好的异常处理不仅能防止程序崩溃,还能提供有用的错误信息,帮助用户理解问题所在并采取相应措施。