Python中使用变量重新赋值的文件缓冲刷新与关闭
我最近在使用Python处理文件时遇到了一些有趣的事情,想确认一下我理解得对不对。给你看看:
[Python 2.7 shell]
...
model = (really big Numpy model)
f = open('file.out','w')
pickle.dump(model, f)
(pickle.dump() finishes while I'm doing other things)
[Bash shell]
$ ls -l
-rw-r--r-- 1 john staff 270655488 Dec 6 21:32 file.out
[返回Python shell]
model = (different really big Numpy model)
f = open('newfile.out','w')
pickle.dump(model,f)
(pickle.dump() finishes)
[Bash shell]
$ ls -l
-rw-r--r-- 1 john staff 270659455 Dec 7 07:09 file.out
-rw-r--r-- 1 john staff 270659451 Dec 6 20:48 newfile.out
注意,file.out现在的大小变了。
我知道Python的文件缓冲区默认是系统的大小(我用的是Mac OSX),所以在我操作的时候,文件缓冲区里还有3967个字节,而Mac的文件缓冲区比这个要大。
让我感兴趣的是,我在没有调用f.close()的情况下,强行把文件对象'f'重新指向了另一个打开的文件(老实说,我只是想快点测试其他东西,结果忘了)。当我查看文件大小时,我半期待它保持不变(这可能意味着输出被截断了)。
所以,我想问的是,这样做是否安全?文件对象的重新赋值是否有某种机制,能够让Python的垃圾回收器或者文件对象自己在这种突发的变量重新赋值时,自动刷新缓冲区并关闭文件,即使你没有调用close()方法?更重要的是,这种情况是总是这样的吗?还是说在某些情况下,变量重新赋值可能确实会,或者在其他情况下可能会在文件缓冲区刷新之前截断那个缓冲区。
我想这其实是个关于文件对象和Python垃圾回收器在没有适当销毁的情况下,处理对象时的优雅性和安全性的问题。
2 个回答
默认情况下,pickle的dumps使用的是ASCII格式(协议0),所以它的长度取决于实际的数据。如果你想使用二进制格式来保存数据,可以把版本号设置为-1。不过要注意,这样的话你在读取和写入文件时需要用到"wb"和"rb"这两个模式。
只要你的电脑没有崩溃,不关闭文件也不会丢失数据。Python会在文件对象被垃圾回收时自动关闭文件。在你提到的情况中,f
是唯一指向这个文件的名字,所以当你把这个名字用来做其他事情时,文件就被关闭了。
不过,最好还是养成关闭文件的习惯,这样可以释放系统为文件对象分配的资源。在某些情况下,你可能不知道文件对象什么时候会被垃圾回收,比如在出现错误时,文件对象的引用可能会保存在错误追踪信息中,这样就会阻止垃圾回收。所有文件在解释器退出时都会被关闭。