你如何使用weakref或contextlib来关闭打开的文件?

时间:2012-11-12 17:36:30

标签: python

我有一个包含对打开文件的强引用的类。如果代码运行没有任何异常,则文件正确关闭,因为我在关闭文件的类上显式调用了一个方法。但是,如果抛出异常,则文件未正确关闭。

这是我的代码的模拟版本:

class MyFile(object):
    def __init__(self, filename, mode):
        self._handle = open(filename, mode)

    @classmethod
    def open(cls, filename, mode):
        return MyFile(filename, mode)

    def close(self):
        self._handle.close()

    def __del__(self):
        self.close()

    def writerow(data):
        # Special write
        pass

    def __enter__(self):
        return self

    def __exit__(self, *exc_info):
        self.close()

现在如果我在我的代码的顶层使用这个类,我会使用with语句:

def get_some_dat():
    return 1

with MyFile.open('foo.txt', 'w') as f:
    # do stuff with f
    data = get_some_data()
    f.writerow(data)

但是,MyFile是由另一个对象间接打开的。我知道大多数Pythonist会说我应该显式关闭文件,但我想确保在销毁对象时关闭文件。我编写的代码可以解决这个问题,但我想知道是否有人对更好的实现此行为的方法提出了建议。

1 个答案:

答案 0 :(得分:2)

以下是使用weakref确保文件已关闭的示例,即使文件未使用with ...语法打开也是如此:

import weakref

class FileHandler:
    def __init__(self, dbf, caller = None):
        if caller is not None:
            self._ref = weakref.ref(caller, self.close)
        self.thefile = open(dbf, 'rb')
    def __enter__(self):
        return self
    def __exit__(self, ext_type, exc_value, traceback):
        self.close()
    def close(self, *args):
        print('closing file')
        self.thefile.close()

class Foo:
    def __init__(self):
        self.fh = FileHandler('/tmp/testfile', caller = self)

def autoclosing_file():
    foo = Foo()

def demo_callback():
    with open('/tmp/testfile', 'w'): pass
    autoclosing_file()


if __name__ == '__main__':
    demo_callback()

打印

closing file
PS:我怀疑这段代码不是我的,但我已经丢失了它的来源。如果有人知道,请说明我可以给予正确的归属。

相关问题