Python文件对象,结束和析构函数

Nik*_*tio 6 python file-io destructor

tempfile.NamedTemporaryFile()说的描述:

如果delete为true(默认值),则文件一关闭就会被删除.

在某些情况下,这意味着在Python解释器结束后不会删除该文件.例如,在下面运行以下测试时 py.test,临时文件仍然是:

from __future__ import division, print_function, absolute_import
import tempfile
import unittest2 as unittest
class cache_tests(unittest.TestCase):
    def setUp(self):
        self.dbfile = tempfile.NamedTemporaryFile()
    def test_get(self):
        self.assertEqual('foo', 'foo')
Run Code Online (Sandbox Code Playgroud)

在某种程度上这是有道理的,因为该程序从不显式关闭文件对象.对象关闭的唯一另一种方式可能是在__del__析构函数中,但是这里语言引用指出" 不保证__del__()在解释器退出时仍然存在的对象调用方法. "所以一切都与迄今为止的文件.

但是,我对此的含义感到困惑.如果不能保证在解释器出口处关闭文件对象,那么即使程序正常退出,也可能发生成功写入(缓冲)文件对象的某些数据丢失,因为它仍然在文件对象的缓冲区中,文件对象永远不会关闭?

不知何故,这对我来说似乎非常不可能和非pythonic,open()文档也不包含任何此类警告.所以我(暂时)得出结论,文件对象毕竟是保证关闭的.

但是这个魔法是如何发生的,为什么不能NamedTemporaryFile()使用相同的魔法来确保文件被删除?

编辑:请注意,我不是在谈论文件描述符(由操作系统缓冲并在程序退出时由操作系统关闭),而是关于可能实现自己缓冲的Python文件对象.

Arm*_*igo 14

在Windows上,NamedTemporaryFile使用特定于Windows的扩展(os.O_TEMPORARY)来确保文件在关闭时被删除.如果该过程以任何方式被杀死,这可能也有效.但是在POSIX上没有明显的等价物,很可能是因为在POSIX上你可以简单地删除仍在使用的文件; 它只删除名称,文件的内容仅在关闭后以任何方式删除.但实际上假设我们希望文件名在文件关闭之前一直存在,就像使用NamedTemporaryFile一样,那么我们需要"魔术".

我们不能使用与刷新缓冲文件相同的魔力.发生的事情是C库处理它(在Python 2中):文件是C中的FILE对象,C保证它们在正常程序退出时被刷新(但是如果进程被杀死则不会).在Python 3的情况下,有自定义C代码来实现相同的效果.但它特定于此用例,而不是任何可直接重用的用例.

这就是NamedTemporaryFile使用自定义的原因__del__.事实上,__del__当解释器退出时,不能保证被调用.(我们可以使用引用NamedTemporaryFile实例的全局引用循环来证明它;或者运行PyPy而不是CPython.)

作为旁注,NamedTemporaryFile可以更加健壮地实现,例如通过注册自身atexit来确保文件名被删除.但你也可以自己调用它:如果你的进程没有使用无限数量的NamedTemporaryFiles,那就简单了atexit.register(my_named_temporary_file.close).