在Python编程中,异常是程序运行时发生的错误,它会中断程序的正常执行流程。异常处理机制使得程序能够捕获这些错误,并进行适当的处理,从而避免程序崩溃。
1 错误类型
代码的错误一般会有语法错误和异常错误两种,语法错误就是代码没有按照 Python 规定语法去写导致程序无法执行,比如代码的格式、缩进等。另外一种是异常错误,即使语法正确,程序在运行过程中也可能会出错,比如用户输入了错误的内容,列表的索引不存在,字典的key不存在等等。
使用异常处理可以在异常错误的时候,执行特定的逻辑,让程序可以继续执行,如果不对异常捕获,程序将终止执行。
异常的分类
(1)内置异常类
- zeroDivisionError:除(或取模)零
- IndexError:序列中没有此索引(index)
- KeyError:映射中没有这个键
- SyntaxError:Python 语法错误
- OSError:操作系统异常(如:文件打开异常)
- keyboardInterrupt:键盘中断错误,Ctrl+c使得程序异常退出
- RuntimeError:运行时错误
- Exception:所有异常的父类
(2)自定义异常类
可以通过自定义类,继承 Exception 实现。
2 捕获异常
2.1 捕获常规异常
try:
可能发生错误的代码
except:
如果出现异常执行的代码
示例如下:
需求:尝试以`r`模式打开文件,如果文件不存在,则以`w`方式打开。
try:
f = open('linux.txt', 'r')
except:
f = open('linux.txt', 'w')
2.2 捕获指定异常
try:
print(name)
except NameError as e:
print('name变量名称未定义错误')
注意事项:
- 如果尝试执行的代码的异常类型和要捕获的异常类型不一致,则无法捕获异常。
- 一般try下方只放一行尝试执行的代码。
2.3 捕获多个异常
当捕获多个异常时,可以把要捕获的异常类型的名字,放到except 后,并使用元组的方式进行书写。
try:
print(1/0)
except (NameError, ZeroDivisionError) as e:
print(e)
结果如下:
也可以使用带有分支的异常处理,如下:
try:
# 可能会引发异常的代码
print(1/0)
except ValueError as ve:
# 处理ValueError的代码
print(f"ValueError occurred: {ve}")
except ZeroDivisionError as ze:
# 处理ValueError的代码
print(f"ZeroDivisionError occurred: {ze}")
except TypeError as te:
# 处理TypeError的代码
print(f"TypeError occurred: {te}")
except Exception as e:
# 处理其他所有类型的异常
print(f"An error occurred: {e}")
结果如下:
2.4 捕获所有异常
try:
print(name)
except Exception as e:
print(e)
结果如下:
2.5 捕获else分支
还可以使用 else 和 finally 子句。
- else:当try块中的代码没有引发异常时,执行else块的代码。
- finally:无论是否发生异常,finally块的代码总会执行。
try:
f = open('test.txt', 'r')
except Exception as e:
f = open('test.txt', 'w')
else:
print('没有异常,真开心')
finally:
f.close()
3 抛出异常
在Python中,可以使用 raise 关键字手动抛出异常。
def divide(x, y):
if y == 0:
raise ValueError("y cannot be zero")
return x / y
divide(4, 2)
divide(3, 0)
结果如下:
可以在函数或代码块中根据需要抛出特定类型的异常,以便在其他地方进行捕获和处理。
4 自定义异常
有时标准异常不足以描述特定的错误情况,可以通过创建自定义异常类来定义新的异常类型
class CustomError(Exception):
"""自定义异常类"""
def __init__(self, message):
self.message = message
def __str__(self):
return f"CustomError: {self.message}"
# 使用自定义异常
try:
raise CustomError("This is a custom error")
except CustomError as ce:
print(ce)
结果如下:
5 异常传递
当一个异常在函数中未被处理时,该异常会向上传递到调用该函数的地方,直到被捕获或到达程序的顶层,从而导致程序崩溃。
- read_file函数试图打开一个文件,如果文件不存在,会捕获FileNotFoundError并抛出一个自定义的CustomError。
- process_file函数调用read_file并尝试处理文件内容,如果发生CustomError,会捕获并重新抛出。
- 最外层的try...except语句最终捕获并处理CustomError,输出错误信息。
class CustomError(Exception):
"""自定义异常类"""
def __init__(self, message):
self.message = message
def __str__(self):
return f"CustomError: {self.message}"
def read_file(file_path):
try:
with open(file_path, 'r') as file:
return file.read()
except FileNotFoundError as e:
raise CustomError(f"File not found: {file_path}") from e
def process_file(file_path):
try:
content = read_file(file_path)
# 假设这里有其他处理文件内容的代码
return content
except CustomError as ce:
print(ce)
raise
try:
file_content = process_file("non_existent_file.txt")
except CustomError as ce:
print(f"Handled at top level: {ce}")
结果如下: