Python:由文件关闭引起的对with语句的探索

文件关闭中的with as

在操作文件的时候,通常为了避免不必要的问题(程序退出时,因为垃圾回收机制,程序也会自动的关闭文件对象,但是这是我们不可控的;在有些操作系统和设置中,关闭文件可以避免无意义地锁定文件),我们通常要在打开文件之后要去关闭文件。
如果对文件进行了写入操作的时候,一定要注意将其关闭,因为Python可能缓冲写入的数据(将数据暂时保存在内存区,提高程序运行效率),因此如果程序抛出异常或者因为某种原因而中断,那么数据可能无法写入到文件中,所以想要保证数据安全的话,使用完文件后就将其关闭!如果想要暂时不关闭文件,但是又想要重置缓冲,让所做的文件修改立即反应到磁盘上的文件中,可以使用文件对象的flush方法。
python的实现中,调用write后,只是把数据写到内核缓冲区,实际上并没有把数据写到磁盘上,只有调用close或是内核缓冲区满的情况下,数据才会写入磁盘中。调用文件对象的flush函数,在每次写入文件的时候把数据输出到磁盘(加载到缓冲区),然而,需要注意的是,根据使用的操作系统和设置,flush可能出于锁定考虑而禁止其他正在运行的程序访问这个文件。而且系统频繁的将数据写到磁盘,会比较耗CPU。
所以说,如果没有特别的需求,尽可能的关闭文件。

要确保文件得以关闭,可使用一条try/finally语句,并在finally子句中调用close。

# 打开文件
f = open('test.txt','w+')
try:
	# 将数据写入到文件中
	f.write('Test')
finally:
	# 无论程序是否异常,确保关闭文件
	f.close()

上面是一种写法,Python提供了with as结构,这是专门为此设计的语句。

with open('test.txt', 'w+') as f:
	f.write('Test')
	# do_something_else(f)
#到这里时文件已关闭

with 语句打开了文件,然后将文件对象赋给了变量f,在with语句体中,执行数据写入及其他文件操作。当程序执行到语句体末尾的时候,将自动关闭文件。出现异常程序中断的时候同样会自动关闭文件。


文件用作上下文管理器,这样文件在执行清理工作时候关闭了自己。
下面说说with语句,探讨为什么会有这样的流程”:

with 语句是一个非常通用的结构,用于包装使用上下文管理器的代码块,让管理器能够执行一些设置和清理操作。
- 什么是上下文管理器?
	答:上下文管理器是内部实现了(__enter__和__exit__)两个方法的对象。也就说我们要想

__enter__方法:
对象的__enter__方法不接受任何参数,在进入with语句时被调用,方法的返回值被赋给关键字as后面的变量。

__exit__方法:
对象的__exit__要接受三个参数:异常类型、异常对象和异常跟踪。
语句执行结束或者如果语句块内部发生了异常,__exit__方法将被调用,而异常将会被重新抛出(re-raised)。
如果__exit__返回false,将抑制所有异常(异常信息会在执行exit方法后被抛出,在Python中函数不设置不返回值,默认会返回None,同样是假值,也会抛出所有异常)。
如果返回True,最终会忽略语句块中发生的所有异常(大部分情况下这都不是明智之举)。

那么我们可以分析出文件作为上下文管理器的简要流程:open函数返回文件对象,文件对象作为上下文管理器,它的__enter__方法返回文件对象本身 ,__exit__方法中实现了关闭文件的操作。


文件对象、线程锁、socket 对象 等 都可以使用 with 操作

下面我们自定义一个上下文管理器

class CustomContextor(object):
    def __init__(self):
        pass

    def test(self):
        print("test")

    def __enter__(self):
        print("进入enter方法")
        # 不返回管理器对象的话也是能用的,但是无法调用test方法
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("with 执行完毕,自动调用exit!")
        return False


with CustomContextor() as c:
    c.test()

print('程序结束')

运行结果如下:
Python:由文件关闭引起的对with语句的探索_第1张图片
我们修改以下代码,让程序在代码块中抛出异常异常的话:

class CustomContextor(object):
    def __init__(self):
        pass

    def test(self):
        print("test")

    def __enter__(self):
        print("进入enter方法")
        # 不返回管理器对象的话也是能用的,但是无法调用test方法
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("with 执行完毕,自动调用exit!")
        return False


with CustomContextor() as c:
    raise Exception()
    c.test()

print('程序结束')

Python:由文件关闭引起的对with语句的探索_第2张图片


contextlib是一个Python模块,这个库是提供更易用的上下文管理器
关于这个只是可以参考下面的链接 深入解析Python中的上下文管理器


参考书籍及文章:
《Beginning Python From Novice to Professional》
Python使用flush函数将缓冲区数据立即写入

你可能感兴趣的:(Python,with,as,文件关闭,上下文管理)