异常处理

异常处理

Yiuhang Chan

异常(Exception)

在Python中,异常(Exception)是程序执行过程中发生的错误事件。当Python检测到一个错误时,它会引发一个异常。异常是Python用来管理程序执行中错误的一种机制。

异常的基本概念

  1. 异常 (Exception): 这是程序执行中发生的异常事件。在Python中,异常是一个对象,表示一个错误。
  2. 引发异常 (Raise an Exception): 当Python解释器遇到一个错误时,它会”引发”一个异常。程序员也可以在代码中显式地引发异常。
  3. 捕获异常 (Catch/Handle an Exception): 使用tryexcept语句来捕获并处理异常。这允许程序在发生异常时优雅地恢复,而不是完全崩溃。
  4. try块 (try block): 这是用来测试可能引发异常的代码块。
  5. except块 (except block): 当try块中的代码触发异常时执行的代码块。可以指定捕获特定类型的异常。
  6. finally块 (finally block): 无论是否发生异常,finally块中的代码都会执行。常用于执行清理操作,如关闭文件。
  7. else块 (else block): 如果try块没有引发异常,则执行else块中的代码。

异常类型

ValueError

当传递给函数的参数类型正确,但值不适当或不在预期范围内时,将引发ValueError

1
2
3
4
5
6
7
8
def convert_to_int(text):
try:
return int(text)
except ValueError:
return "请提供一个有效的整数字符串"

print(convert_to_int("123")) # 输出: 123
print(convert_to_int("abc")) # 输出: 请提供一个有效的整数字符串

TypeError

当操作或函数应用于类型不正确的对象时,会引发TypeError

1
2
3
4
5
6
7
8
def add_numbers(a, b):
try:
return a + b
except TypeError:
return "两个参数都必须是数字"

print(add_numbers(10, 20)) # 输出: 30
print(add_numbers(10, "20")) # 输出: 两个参数都必须是数字

IndexError

当尝试访问序列中不存在的索引时,会引发IndexError

1
2
3
4
5
my_list = [1, 2, 3]
try:
print(my_list[3])
except IndexError:
print("索引超出了列表的范围")

KeyError

当在字典中查找不存在的键时,会引发KeyError

1
2
3
4
5
my_dict = {"name": "Alice", "age": 25}
try:
print(my_dict["gender"])
except KeyError:
print("键不存在")

IOError

当尝试执行一个与输入/输出相关的操作(如打开不存在的文件)时,会引发IOError(在Python 3中,通常是OSError或其子类)。

1
2
3
4
5
try:
with open("nonexistent_file.txt") as f:
content = f.read()
except IOError:
print("文件打开失败")

ZeroDivisionError

当尝试将一个数字除以零时,会引发ZeroDivisionError

1
2
3
4
try:
result = 10 / 0
except ZeroDivisionError:
print("除以零错误")

AttributeError

当尝试访问对象不存在的属性或方法时,会引发AttributeError

1
2
3
4
5
6
7
8
9
class MyClass:
def __init__(self):
self.name = "ChatGPT"

try:
obj = MyClass()
print(obj.age) # obj没有定义age属性
except AttributeError:
print("属性不存在")

FileNotFoundError

在尝试打开一个不存在的文件时,Python 3中会引发FileNotFoundError,这是OSError的一个子类。

1
2
3
4
5
try:
with open("some_nonexistent_file.txt") as f:
content = f.read()
except FileNotFoundError:
print("文件未找到")

ImportError

当尝试导入一个不存在的模块时,会引发ImportError

1
2
3
4
try:
import non_existent_module
except ImportError:
print("模块无法导入")

OverflowError

当一个算术运算产生的结果太大而无法表示时,会引发OverflowError

1
2
3
4
5
6
import math
try:
# 这可能会引发OverflowError
print(math.exp(1000))
except OverflowError:
print("数值溢出")

NameError

当尝试访问一个尚未声明/定义的局部或全局变量时,会引发NameError

1
2
3
4
try:
print(undefined_variable)
except NameError:
print("变量未定义")

RecursionError

当递归过深超过最大递归深度时,会引发RecursionError。这是RuntimeError的一个子类。

1
2
3
4
5
6
7
def recursive_function():
recursive_function()

try:
recursive_function()
except RecursionError:
print("递归过深")

这些例子涵盖了Python中的一些其他常见异常类型。理解和处理这些异常对于编写稳健的Python程序至关重要。

SyntaxError

当Python解释器遇到语法错误时,会引发SyntaxError。这通常发生在代码编写不正确时。

1
2
3
4
try:
exec("for i in range(5) print(i)") # 缺少冒号
except SyntaxError:
print("发生了语法错误")

IndentationError

当代码的缩进不正确时,会引发IndentationError,这是SyntaxError的一个子类。

1
2
3
4
try:
exec("def foo():\nprint('Hello')")
except IndentationError:
print("缩进错误")

AssertionError

assert语句失败时,会引发AssertionErrorassert用于调试阶段的自我检查。

1
2
3
4
5
try:
assert 2 + 2 == 5, "计算错误"
except AssertionError as e:
print("断言错误:", e)

KeyboardInterrupt

当用户中断程序执行(通常是通过按Ctrl+C),会引发KeyboardInterrupt

1
2
3
4
5
try:
while True:
continue
except KeyboardInterrupt:
print("程序被用户中断")

MemoryError

当程序运行时内存不足,无法执行操作时,会引发MemoryError

1
2
3
4
try:
large_list = [0] * 10**10
except MemoryError:
print("内存不足")

StopIteration

在使用迭代器时,当没有更多的项可以返回时,会自动引发StopIteration

1
2
3
4
5
6
7
8
iterator = iter([1, 2, 3])
next(iterator) # 1
next(iterator) # 2
next(iterator) # 3
try:
next(iterator) # 迭代完毕
except StopIteration:
print("迭代器没有更多元素")

EnvironmentError

EnvironmentError是在与外部环境(如操作系统)交互时可能遇到的错误的基类。在Python 3中,它被分为更具体的异常,如OSError

其它

这并不是一个完整的列表:

  • ArithmeticError: 所有数值计算错误的基类。
  • BufferError: 与缓冲区相关的操作无法执行时。
  • EOFError: 当input()遇到文件结束标记(EOF)时。
  • FloatingPointError: 浮点计算错误。
  • LookupError: 索引或键查询错误的基类,IndexErrorKeyError是它的子类。
  • ReferenceError: 当试图访问一个已经被垃圾回收器回收的资源时。
  • RuntimeError: 通常发生在检测到不属于其他类别的错误时。
  • SystemError: 解释器系统错误。
  • UnicodeError: Unicode相关的错误,是ValueError的一个子类。
  • UnicodeEncodeError: Unicode编码时的错误。
  • UnicodeDecodeError: Unicode解码时的错误。
  • UnicodeTranslateError: Unicode转换时的错误。

异常处理的语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
try:
# 尝试执行的代码
pass
except ExceptionType1:
# 处理ExceptionType1
pass
except ExceptionType2:
# 处理ExceptionType2
pass
except (ExceptionType3, ExceptionType4):
# 处理多种异常
pass
except:
# 处理未指定的其他异常
pass
else:
# 如果没有异常发生,则执行此处代码
pass
finally:
# 无论是否有异常,都会执行此处代码
pass

捕获特定异常

在Python中,可以使用try-except块来捕获特定类型的异常。这允许您对特定错误进行专门的错误处理。

1
2
3
4
5
try:
# 可能会引发异常的代码
result = 10 / 0
except ZeroDivisionError:
print("捕获到除以零的异常")

捕获所有异常

捕获所有异常并且仅打印出错误信息,可以使用一个通用的 except Exception as e 块。这将捕获所有继承自 Exception 的错误(几乎包括了Python中所有的标准异常)

1
2
3
4
5
try:
# 可能会引发异常的代码
result = 10 / 0
except Exception as e:
print(f"发生错误: {e}")

使用finally块

无论是否发生异常,finally块中的代码都会被执行。这非常适合用来执行清理操作,如关闭文件或释放资源。

1
2
3
4
5
6
7
8
try:
file = open("test.txt", "r")
data = file.read()
except IOError as e:
print(f"读取文件时发生错误:{e}")
finally:
file.close()
print("文件已关闭")

主动抛出异常

可以使用raise语句来主动引发异常。这在需要根据特定条件显式地触发错误时非常有用。

1
2
3
4
5
6
7
8
9
10
11
12
def check_age(age):
if age < 0:
raise ValueError("年龄不能为负数")
elif age < 18:
print("未成年")
else:
print("成年")

try:
check_age(-5)
except ValueError as e:
print(f"捕获到异常:{e}")

使用断言(assert)

断言是一种调试辅助工具,用于检查一个条件是否为真。如果条件为假,将引发AssertionError

1
2
3
4
5
6
7
8
def check_age(age):
assert age >= 0, "年龄不能为负数"
# 其余处理

try:
check_age(-5)
except AssertionError as e:
print(f"捕获到异常:{e}")

信息

  • 断言:通常用于内部一致性检查,表示“这里不可能出错,除非程序内部逻辑有问题”。
  • 异常:更适合于处理程序执行过程中可能遇到的预期错误情况,例如不满足输入条件、资源不可用等。
  • 标题: 异常处理
  • 作者: Yiuhang Chan
  • 创建于 : 2018-10-05 08:15:10
  • 更新于 : 2024-02-28 18:49:16
  • 链接: https://www.yiuhangblog.com/2018/10/05/20181005异常/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论