一、with语句
背景:文件使用完后必须关闭,因为文件对象会占用操作系统的资源,并且操作系统同一时间能打开的文件数量也是有限的
1. 原始方式打开文件
- 问题:文件读写时都有可能产生IOError,一旦出错,后面的
f.close()
就不会调用(风险写法)
- 解决方式:添加try-except-finally语句(安全写法)
- 缺点:代码过于冗长
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| f = open("1.txt", "r") f.write("hello world") f.close() try: f = open("1.txt", "r") f.write("xxxxx")
except IOError as e: print("文件操作出错", e)
finally: f.close()
|
2. with方式打开文件
- 优点:with 语句执行完成以后自动调用关闭文件操作,即使出现异常也会自动调用关闭文件操作
- 原理:上下文管理器(实现__enter__和__exit__)
1 2 3 4
| with open("1.txt", "w") as f: f.write("hello world")
|
二、上下文管理器的创建方式
1. 类方法实现方式
包含__enter__()
和__exit__()
两个方法的类,通过该类创建的对象可称为上下文管理器
__enter__()
:表示上文方法,需要返回一个操作对象
__exit__()
:表示下文方法,with语句执行完成会自动执行,即使出现异常也会执行该方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
class File(object):
def __init__(self, file_name, file_model): self.file_name = file_name self.file_model = file_model
def __enter__(self): print("进入上文方法") self.file = open(self.file_name,self.file_model) return self.file
def __exit__(self, exc_type, exc_val, exc_tb): print("进入下文方法") self.file.close()
if __name__ == '__main__':
with File("1.txt", "r") as file: file_data = file.read() print(file_data)
|
2. 函数装饰器实现方式
Python 还提供了一个 @contextmanager 的装饰器,更进一步简化了上下文管理器的实现方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| from contextlib import contextmanager
@contextmanager def my_open(path, mode): try: file = open(path, mode) yield file except Exception as e: print(e) finally: print("over") file.close()
with my_open('out.txt', 'w') as f: f.write("hello , the simplest context manager")
|