异常处理
- Python 异常处理是一种机制,用于在程序执行过程中处理和管理错误或异常情况。当程序出现错误或异常时,可以使用异常处理来捕获并处理这些异常,以避免程序崩溃或产生不可预料的结果。
- 在 Python 中,异常是指在程序执行期间发生的错误或异常情况。当异常发生时,程序会抛出一个异常对象,可以通过异常处理来捕获并对其进行处理。
异常名称 | 描述 |
---|---|
BaseException | 所有异常的基类 |
SystemExit | 解释器请求退出 |
KeyboardInterrupt | 用户中断执行(通常是输入^C) |
Exception | 常规错误的基类 |
StopIteration | 迭代器没有更多的值 |
GeneratorExit | 生成器(generator)发生异常来通知退出 |
StandardError | 所有的内建标准异常的基类 |
ArithmeticError | 所有数值计算错误的基类 |
FloatingPointError | 浮点计算错误 |
OverflowError | 数值运算超出最大限制 |
ZeroDivisionError | 除(或取模)零 (所有数据类型) |
AssertionError | 断言语句失败 |
AttributeError | 对象没有这个属性 |
EOFError | 没有内建输入,到达EOF 标记 |
EnvironmentError | 操作系统错误的基类 |
IOError | 输入/输出操作失败 |
OSError | 操作系统错误 |
WindowsError | 系统调用失败 |
ImportError | 导入模块/对象失败 |
LookupError | 无效数据查询的基类 |
IndexError | 序列中没有此索引(index) |
KeyError | 映射中没有这个键 |
MemoryError | 内存溢出错误(对于Python 解释器不是致命的) |
NameError | 未声明/初始化对象 (没有属性) |
UnboundLocalError | 访问未初始化的本地变量 |
ReferenceError | 弱引用(Weak reference)试图访问已经垃圾回收了的对象 |
RuntimeError | 一般的运行时错误 |
NotImplementedError | 尚未实现的方法 |
SyntaxError | Python 语法错误 |
IndentationError | 缩进错误 |
TabError | Tab 和空格混用 |
SystemError | 一般的解释器系统错误 |
TypeError | 对类型无效的操作 |
ValueError | 传入无效的参数 |
UnicodeError | Unicode 相关的错误 |
UnicodeDecodeError | Unicode 解码时的错误 |
UnicodeEncodeError | Unicode 编码时错误 |
UnicodeTranslateError | Unicode 转换时错误 |
Warning | 警告的基类 |
DeprecationWarning | 关于被弃用的特征的警告 |
FutureWarning | 关于构造将来语义会有改变的警告 |
OverflowWarning | 旧的关于自动提升为长整型(long)的警告 |
PendingDeprecationWarning | 关于特性将会被废弃的警告 |
RuntimeWarning | 可疑的运行时行为(runtime behavior)的警告 |
SyntaxWarning | 可疑的语法的警告 |
UserWarning | 用户代码生成的警告 |
基本语法
try-except
语句
try
块用于包含可能会引发异常的代码,except
块用于捕获并处理异常。语法如下:1
2
3
4try:
# 可能引发异常的代码
except ExceptionType:
# 异常处理代码- 在
try
块中的代码执行期间,如果发生了指定类型的异常,那么程序会跳转到对应的except
块中执行异常处理代码。如果没有发生异常,则except
块会被跳过。 - 此外,还可以使用
as
关键字将捕获的异常赋值给一个变量,以便进一步处理或分析异常信息。例如:1
2
3
4try:
# 可能引发异常的代码
except ValueError as e:
# 处理 ValueError 异常的代码,可以使用 e 变量获取异常对象
捕获多个异常
- 在Python中,可以使用多个
except
语句来捕获多个异常。这样可以根据不同的异常类型执行相应的处理逻辑。具体的语法如下:1
2
3
4
5
6
7
8
9try:
# 可能引发异常的代码
except ExceptionType1:
# 处理 ExceptionType1 异常的代码
except ExceptionType2:
# 处理 ExceptionType2 异常的代码
...
except ExceptionTypeN:
# 处理 ExceptionTypeN 异常的代码 - 在上述代码中,
try
块中的代码执行期间,如果发生了指定类型的异常,程序会跳转到对应的except
块中执行异常处理代码。如果没有发生异常或发生的异常类型不在指定的异常类型列表中,则except
块会被跳过。 - 可以根据需要捕获多个不同类型的异常,每个
except
块可以处理不同的异常类型。如果多个异常类型具有相同的处理逻辑,可以将它们放在同一个except
块中,用逗号分隔(分组处理)。下面是一个示例,演示了如何捕获多个异常:1
2
3
4
5
6
7
8try:
# 可能引发异常的代码
except ValueError:
# 处理 ValueError 异常的代码
except ZeroDivisionError:
# 处理 ZeroDivisionError 异常的代码
except (TypeError, IndexError):
# 处理 TypeError 和 IndexError 异常的代码 - 在上述代码中,
try
块中的代码执行期间,如果发生了ValueError
异常,则程序会跳转到第一个except
块中处理;如果发生了ZeroDivisionError
异常,则程序会跳转到第二个except
块中处理;如果发生了TypeError
或IndexError
异常,则程序会跳转到第三个except
块中处理。 - 需要注意的是,多个
except
块的顺序很重要。Python会按照从上到下的顺序依次匹配异常类型,只会执行第一个匹配的except
块。如果多个异常类型之间存在继承关系,应该将子类的异常类型放在父类的异常类型之前,以确保异常类型的匹配顺序正确。
else
语句
else
块可选,用于在try
块中的代码执行完毕且没有发生异常时执行。语法如下:
1 | try: |
如果try
块中的代码执行完毕且没有发生异常,那么程序会跳转到else
块中执行。
finally
语句
finally
块可选,用于包含无论是否发生异常都需要执行的代码。无论是否发生异常,finally
块中的代码都会被执行。语法如下:
1 | try: |
finally
块通常用于释放资源或执行清理操作,比如关闭文件或数据库连接。
综合示例
1 | try: |
raise
语句
raise
语句用于在Python中显式地触发异常。它允许程序员手动引发异常,并将异常对象传递给异常处理机制。通过使用raise
语句,可以在特定条件下主动引发异常,以便控制程序的流程和错误处理。raise
语句的基本语法如下:1
raise ExceptionType("error message")
- 其中,
ExceptionType
表示要引发的异常类型,可以是内置的异常类型(如ValueError
、TypeError
等),也可以是自定义的异常类型。"error message"
是可选的错误消息,用于提供关于异常的额外信息。 - 下面是一个简单的示例,演示了如何使用
raise
语句引发异常:1
2
3
4
5
6
7
8
9
10
11def divide(a, b):
if b == 0:
raise ValueError("除数不能为零")
return a / b
try:
result = divide(10, 0)
except ValueError as e:
print("捕获到异常:", e) - 在上述代码中,
divide
函数用于执行除法运算。在函数内部,我们使用条件判断来检查除数是否为零,如果为零,则使用raise
语句引发ValueError
异常,并提供错误消息。 - 在
try
块中调用divide
函数时,由于除数为零,会触发ValueError
异常。然后,异常被捕获并赋值给e
变量,在except
块中打印异常信息。 - 使用
raise
语句可以灵活地控制程序的异常处理流程。通过根据特定条件引发异常,我们可以在需要的地方中断程序的执行,并通过异常处理机制来处理异常情况。这可以帮助我们更好地管理错误和异常,并提供有用的错误信息。
嵌套异常
- 嵌套异常是指在处理异常时,一个异常的处理过程中又引发了另一个异常。当发生嵌套异常时,内部异常会覆盖外部异常,而外部异常则成为内部异常的上下文。
- 在Python中,可以通过在
except
块内部使用raise
语句来引发新的异常,从而实现嵌套异常。这可以在处理异常时,根据需要引发新的异常,以提供更具体的错误信息或执行额外的错误处理逻辑。 - 下面是一个简单的示例,演示了嵌套异常的概念:
1
2
3
4
5
6
7
8
9try:
try:
# 可能引发异常的代码
except ExceptionType1:
# 处理 ExceptionType1 异常的代码
raise ExceptionType2("内部异常")
except ExceptionType2 as e:
# 处理 ExceptionType2 异常的代码,可以访问内部异常的上下文信息
print("捕获到内部异常:", e) - 在上述代码中,我们使用了嵌套的
try-except
块。内部的try
块用于执行可能引发异常的代码,如果发生了ExceptionType1
异常,会跳转到内部的except
块中处理。在内部的except
块中,我们使用raise
语句引发了一个新的ExceptionType2
异常,并提供了错误消息。 - 外部的
try-except
块用于处理内部引发的异常。如果发生了ExceptionType2
异常,会跳转到外部的except
块中处理,并打印异常信息。 - 嵌套异常允许我们在异常处理过程中引发新的异常,从而提供更多的上下文信息或执行额外的错误处理逻辑。但需要注意,在处理嵌套异常时,要确保适当地处理内部和外部异常,以避免异常被忽略或引发未处理的异常。
自定义异常
- 在Python中,我们可以通过创建自定义异常类来定义自己的异常。自定义异常可以用于在特定条件下引发异常,并提供更具体的错误信息或执行特定的错误处理逻辑。
- 自定义异常类可以继承自内置的异常类(如
Exception
、ValueError
等),也可以继承自其他自定义异常类。通常,我们会选择继承自适当的内置异常类,以便在异常处理过程中能够正确地捕获和处理自定义异常。 - 下面是一个示例,演示了如何创建自定义异常类:
1
2
3class MyCustomException(Exception):
pass - 在上述代码中,我们创建了一个名为
MyCustomException
的自定义异常类,它继承自内置的Exception
类。pass
语句表示该类不包含任何额外的定义,因此它只是一个简单的自定义异常类。 - 可以根据需要在自定义异常类中添加属性和方法,以提供更多的上下文信息或自定义的行为。例如:
1
2
3
4
5
6
7
8class MyCustomException(Exception):
def __init__(self, message, error_code):
super().__init__(message)
self.error_code = error_code
def print_error(self):
print(f"错误代码: {self.error_code},错误信息: {self.args[0]}") - 在上述代码中,我们添加了一个
__init__
方法来接收错误消息和错误代码,并使用super()
调用父类的__init__
方法来设置错误消息。我们还添加了一个print_error
方法,用于打印错误代码和错误信息。 - 使用自定义异常时,可以通过使用
raise
语句引发自定义异常来触发异常情况。例如:1
2
3
4
5
6
7
8
9
10def process_data(data):
if not data:
raise MyCustomException("数据为空", 1001)
try:
process_data([])
except MyCustomException as e:
e.print_error() - 在上述代码中,
process_data
函数用于处理数据。如果数据为空,我们使用raise
语句引发了MyCustomException
异常,并提供了错误消息和错误代码。在except
块中捕获到该异常后,我们可以通过调用print_error
方法打印错误信息。 - 通过创建自定义异常类,我们可以更好地组织和管理异常,并提供更具体的错误信息和自定义的异常处理逻辑。这有助于使代码更具可读性和可维护性,并提供更好的错误诊断和调试能力。
断言
- 简介
断言(Assertion)是一种在程序中检查条件是否满足的方法。在Python中,断言是通过assert
语句实现的。它用于在代码中插入检查点,以确保程序的正确性。 - 语法
1
assert condition, message
其中,
condition
是一个布尔表达式,表示要检查的条件。如果条件为真(True
),则程序继续执行;如果条件为假(False
),则触发AssertionError
异常,并可选地输出指定的错误消息(message
)。 - 工作原理
- 执行
assert
语句时,首先计算条件表达式的值。 - 如果条件为真,则程序继续执行。
- 如果条件为假,则触发
AssertionError
异常。 - 可选地输出指定的错误消息。
- 执行
- 作用
- 调试和测试:断言可用于验证程序的正确性和健壮性。通过在关键位置插入断言语句,可以确保程序的状态和结果符合预期。如果断言失败,就意味着程序存在问题,可以帮助我们快速定位和修复错误。
- 前置条件和后置条件:断言可用于检查函数或方法的输入参数和返回值是否满足预期。通过在函数或方法的开头和结尾处添加断言语句,可以确保输入和输出符合约定和要求。
- 程序逻辑的约束:断言可用于强制执行程序中的逻辑约束。例如,如果在一段代码中假设某个变量的值不会为零,可以使用断言来验证这个假设,并在条件不满足时触发异常。
- 注意事项
需要注意的是,断言通常用于调试和开发阶段,而不是用于处理预期的运行时错误。在生产环境中,可以通过关闭断言来避免性能损失。可以使用-O
选项或设置PYTHONOPTIMIZE
环境变量为2
来禁用断言。 - 示例
1
2
3
4
5
6
7
8
9
10def divide(a, b):
assert b != 0, "除数不能为零"
return a / b
result = divide(10, 2)
print(result) # 输出: 5.0
result = divide(10, 0) # 触发AssertionError异常,并输出错误消息在上述代码中,
divide
函数用于执行除法运算。在函数内部,我们使用断言来检查除数是否为零,如果为零,则触发AssertionError
异常,并输出错误消息。