异常是在程序执行过程中发生的错误条件,它中断了正常的程序流程。
Python中有多种内置异常类型,如ValueError
、TypeError
、IndexError
等。
异常会向上传播直到被捕获,如果没有被捕获,它会导致程序终止。
try-except
语句try-except
使用try-except
语句用于捕获和处理异常。
代码演示:
try:
x = 1 / 0
except ZeroDivisionError:
print("不能除以零")
输出:
不能除以零
except
分支处理不同类型的异常可以有多个except
分支来处理不同类型的异常。
代码演示:
try:
x = int(input("请输入一个整数: "))
if x < 0:
raise ValueError("不能为负数")
except ValueError as e:
print("值错误:", e)
except Exception as e:
print("未知错误:", e)
输出:
值错误: 不能为负数
except Exception
except Exception
可以捕获所有类型的异常。
代码演示:
try:
x = 1 / 0
except Exception as e:
print("异常:", e)
输出:
异常: division by zero
as
关键字as
关键字用于获取异常的实例。
代码演示:
try:
x = 1 / 0
except ZeroDivisionError as e:
print("异常信息:", e)
输出:
异常信息: division by zero
else
子句else
子句中的代码仅在try
块没有发生任何异常时执行。
代码演示:
try:
x = 1 / 1
print("尝试执行成功")
except ZeroDivisionError:
print("异常发生")
else:
print("没有异常发生")
输出:
尝试执行成功
没有异常发生
try-except-else
的完整结构try-except-else
提供了完整的异常处理结构。
代码演示:
try:
# 尝试执行的代码
pass
except:
# 发生异常时执行的代码
pass
else:
# 没有异常发生时执行的代码
pass
输出:
# 根据代码执行情况输出
finally
子句finally
子句用于确保资源被释放,无论是否发生异常。
代码演示:
try:
f = open("file.txt", "w")
f.write("Hello")
except:
print("发生异常")
finally:
f.close()
print("文件已关闭")
输出:
文件已关闭
try-except-finally
的组合使用try-except-finally
提供了完整的异常处理和资源管理结构。
代码演示:
try:
# 尝试执行的代码
pass
except:
# 发生异常时执行的代码
pass
else:
# 没有异常发生时执行的代码
pass
finally:
# 总是执行的代码
pass
输出:
# 根据代码执行情况输出
finally
和异常传播的关系即使finally
块执行,异常仍然会传播。
代码演示:
try:
1 / 0
except:
print("捕获异常")
finally:
print("执行 finally")
输出:
捕获异常
执行 finally
raise
抛出异常raise
关键字用于抛出指定的异常。
代码演示:
x = -1
if x < 0:
raise ValueError("不能为负数")
输出:
Traceback (most recent call last):
...
ValueError: 不能为负数
可以在except
块中重新抛出异常。
代码演示:
try:
x = 1 / 0
except ZeroDivisionError as e:
print("捕获异常")
raise e
输出:
捕获异常
Traceback (most recent call last):
...
division by zero
可以通过继承Exception
类来创建自定义异常。
代码演示:
class MyError(Exception):
pass
try:
raise MyError("自定义异常")
except MyError as e:
print("捕获自定义异常:", e)
输出:
捕获自定义异常: 自定义异常
自定义异常可以在需要特定错误处理逻辑时使用。
代码演示:
class NegativeNumberError(Exception):
pass
def process_number(num):
if num < 0:
raise NegativeNumberError("不能为负数")
print("处理数字:", num)
try:
process_number(-1)
except NegativeNumberError as e:
print("错误:", e)
输出:
错误: 不能为负数
自定义异常可以与内置异常结合使用。
代码演示:
class MyValueError(ValueError):
pass
try:
raise MyValueError("自定义值错误")
except ValueError as e:
print("捕获值错误:", e)
输出:
捕获值错误: 自定义值错误
try-except
结构try-except
结构可以嵌套使用。
代码演示:
try:
try:
x = 1 / 0
except ZeroDivisionError:
print("内部异常")
raise
except Exception as e:
print("外部异常:", e)
输出:
内部异常
外部异常: division by zero
在复杂逻辑中,嵌套的异常处理可以帮助精确捕获和处理异常。
代码演示:
try:
# 外层逻辑
try:
# 内层逻辑
x = 1 / 0
except ZeroDivisionError:
print("处理内部除零错误")
except Exception as e:
print("处理外部异常:", e)
输出:
处理内部除零错误
处理外部异常: division by zero
上下文管理器允许代码在进入和退出上下文时执行特定的操作。
with
语句管理资源with
语句用于管理资源,如文件操作。
代码演示:
with open("file.txt", "w") as f:
f.write("Hello")
输出:
# 文件 file.txt 内容为: Hello
自定义上下文管理器可以在__enter__
和__exit__
方法中处理异常
。
代码演示:
class MyContextManager:
def __enter__(self):
print("进入上下文")
return self
def __exit__(self, exc_type, exc_value, traceback):
print("退出上下文")
if exc_type:
print("处理异常:", exc_value)
with MyContextManager() as manager:
x = 1 / 0
输出:
进入上下文
退出上下文
处理异常: division by zero
应该捕获具体的异常类型,而不是捕获所有异常。
代码演示:
try:
x = int(input("请输入一个整数: "))
except ValueError:
print("请输入一个有效的整数")
输出:
请输入一个有效的整数
except Exception
避免捕获所有异常,因为这可能会隐藏真正的错误。
代码演示:
try:
x = 1 / 0
except Exception:
print("捕获所有异常")
输出:
捕获所有异常
应该记录异常信息以便于调试。
代码演示:
try:
x = 1 / 0
except Exception as e:
print("异常:", e)
输出:
异常: division by zero
可以使用日志系统来记录异常信息。
代码演示:
import logging
logging.basicConfig(level=logging.ERROR)
try:
x = 1 / 0
except ZeroDivisionError as e:
logging.error("除零错误: %s", e)
输出:
ERROR:root:除零错误: division by zero
以上是2.10节“异常处理”的内容,包括异常的概念、try-except
语句、else
和finally
子句、抛出异常、自定义异常、异常的嵌套处理、上下文管理与异常以及异常处理的最佳实践。