用python优雅打开文件及上下文管理协议

有次面试被问到如何优雅地打开一个文件?
 
那就是用with语句,调用过后可以自动关闭。
 
但是为什么使用with语句就可以自动关闭呢,原因就是上下文管理协议。
 
上下文管理协议:包含方法 __enter__() 和 __exit__(),支持该协议的对象要实现这两个方法。
with open('a.txt', 'r') as a, open('b.txt', 'w') as b:
    b.write(a.read()) 
 
读取文件with语句的实现及其调用过程:
class ReadFile(object):
    def __init__(self, filename):
        self.file = open(filename, 'r')
    
    def __enter__(self):
        return self.file
    
    def __exit__(self, type, value, traceback):
        # type, value, traceback 分别代表错误的类型、值、追踪栈
        self.file.close()
        # 返回 True 代表不抛出错误,否则错误会被 with 语句抛出
        return True
 
with ReadFile('test.txt') as file_read:
    for line in file_read.readlines():
        print(line)                
 
 
在调用的时候:
  1、with语句先暂存了ReadFile类的__exit__方法
  2、然后调用ReadFile类的__enter__方法
  3、__enter__方法打开文件,并将结果返回给with语句
  4、上一步的结果被传递给file_read参数
  5、在with语句内对file_read参数进行操作,读取每一行
  6、读取完成之后,with语句调用之前暂存的__exit__方法
  7、__exit__方法关闭了文件
 
要注意的是,在__exit__方法内,我们关闭了文件,但最后返回True,所以错误不会被with语句抛出。否则with语句会抛出一个对应的错误。
 
  当我们写文件时,操作系统往往不会立刻把数据写入磁盘,而是放到内存缓存起来,空闲的时候再慢慢写入。只有调用close()方法时,操作系统才保证把没有写入的数据全部写入磁盘。忘记调用close()的后果是数据可能只写了一部分到磁盘,剩下的丢失了。所以,还是用with语句来得保险。

posted @ 2018-02-26 17:20  超凡-  阅读(516)  评论(0编辑  收藏  举报