异常处理
概述
异常是程序运行时发生的错误。
>>> print(a) Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'a' is not defined >>>在程序发生异常时必须要进行处理,原因如下:
- 防止程序崩溃
- 提供错误信息并修正bug
- 允许程序有序结束或恢复
异常类型
- 内置异常,如IndexError, KeyError, ValueError, TypeError等。
- 自定义异常。
基本的异常处理语法
使用try与except代码块进行异常捕捉。
try: # 可能引发异常的代码 except <ExceptionType>: # 异常时的处理代码 def exp_exception(x, y): try: a = x / y print(f'a = {a}') return a except Exception: print('程序出现异常,异常信息:除数为0') exp_exception(2, 0)执行结果:
程序出现异常,异常信息:除数为0捕获多个异常
为不同的异常使用多个except。
使用元组一次捕获多个异常类型。
try:
pass
except (TypeError, ValueError):
pass
except Exception as e:
passdef multi_exception(x, y):
try:
a = x / y
# b = name
except ZeroDivisionError:
print(‘this is ZeroDivisionError’)
except NameError:
print(‘this is NameError’)multi_exception(2, 0)
使用else和finally子句
else:如果没有异常发生,则执行。
finally:无论有无异常都会执行,常用于资源清理。
try:
# 尝试执行的代码
except :
# 异常时的处理
else:
# 无异常时执行
finally:
# 总会执行的代码def model_exception(x, y):
try:
a = x / y
except:
print(‘程序异常…’)
else:
print(‘程序无异常…’)
finally:
print(‘finally代码块被执行…’)model_exception(2, 1)
抛出异常
使用raise语句主动抛出异常
raise ValueError("A value error occurred.") >>> raise Exception Traceback (most recent call last): File "<stdin>", line 1, in <module> Exception >>> raise NameError('This is NameError') Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: This is NameError >>>断言
使用断言处理预期外的条件
def get_age(age): assert age > 0, "年龄不能为负" return age try: user_age = get_age(-1) except AssertionError as error: print(error)自定义异常
尽管内建异常类包括大部分异常,而且可以满足很多要求,但有时还是要创建自己的异常类。比如需要精确知道问题的根源,就需要使用自定义异常精确定位问题。可以通过创建一个新exception类拥有自己的异常。异常应该继承自Exception类,可以直接继承,也可以间接继承。
class MyError(Exception): def __init__(self): pass def __str__(self): return 'this is self define error' def my_error_test(): try: raise MyError() except MyError as e: print('exception info: ', e) my_error_test()异常案例
在文件读写中使用异常
try: with open('example.txt', 'r') as file: content = file.read() except FileNotFoundError: print("文件未找到") except IOError: print("文件读取过程中出错")文件操作
文件概述
- 文件用于长期存储数据。
- 通常存储在磁盘或其他永久性存储设备上。
文件操作的重要性
- 数据存储和检索。
- 配置文件的读取。
- 日志文件的写入。
- 数据交换。
文件模式
- ‘r’:读取模式。
- ‘w’:写入模式,先清空文件。
- ‘a’:追加模式,写入时从文件末尾添加。
- ‘b’:用于读或写二进制文件。
- ‘+’:读写模式。
文件读取
使用open()函数来打开一个文件进行读取或写入。
file = open('example.txt', 'r') result = file.read() # 读取文件内容 file.close() # 关闭文件对象除了read()方法可以读取文本数据外,Python也提供了其他方法来读取文件内容:
- read(size):读取文件中所有内容或指定长度的字符。
- readline():一次读取一行。
- readlines():读取文件中所有行,作为列表返回。
使用with语法
推荐使用with语句自动处理文件的打开和关闭。
with open('example.txt', 'r') as file: content = file.read()文件写入
使用write()方法写入字符串。
with open('example.txt', 'w') as file: file.write('Hello, World!')多行写入:使用writelines()方法写入字符串列表。
lines = ['Hello, World!', 'Hello, Python!'] with open('example.txt', 'w') as file: file.writelines(line + '\n' for line in lines)注意事项
- 使用’w’模式打开文件会清空原有内容。
- 使用’a’模式进行追加,不会清空原有内容。
文件操作的异常处理
try: with open('example.txt', 'r') as file: content = file.read() except FileNotFoundError as e: print("文件未找到", e)文件指针操作
file.seek(offset, whence):移动文件读取指针到指定位置。
file.tell():返回文件指针的当前位置。
打开文件以更新模式('r+'允许读写)
filename = ‘example.txt’
with open(filename, ‘r+’) as file:
# 写入内容
file.write(‘Hello, Python!\n’)
file.write(‘Python is fun.\n’)# 通过seek方法把文件指针移动到文件的开头 file.seek(0) # 读取并打印文件内容 content = file.read() print(content)
处理二进制文件
以二进制模式rb或wb打开文件。
with open('example.bin', 'wb') as file: file.write(b'\x00\x01\x02')with语句的探究 - 上下文管理器
在文件读写中,我们使用with语句管理文件对象的打开与关闭,那么with语句的具体代码实现是怎样的呢?其实Python调用了两个魔术方法:__enter__方法与__exit__方法。
class CustomFileManager: def __init__(self, filename, mode): self.filename = filename self.mode = mode self.file = None def __enter__(self): print('创建文件对象...') self.file = open(self.filename, self.mode) return self.file def __exit__(self, exc_type, exc_val, exc_tb): if self.file: self.file.close() print('关闭文件对象...') return False # 如果发生了异常,让Python正常地抛出它 # 使用自定义上下文管理器类 with CustomFileManager('example.txt', 'w') as f: f.write('Hello, Python!\n') # 当with语句块执行完成时,文件会被自动关闭。