首页 > 解决方案 > 如何正确关闭类打开的文件?

问题描述

我有一门课用来跟踪 ftp 下载的进度(使用ftplib)。
我使用ftplibwithmultiprocessing一次下载多个文件。
这是我第一次尝试在 Python 中使用类,我怀疑我是否正在关闭我在类中打开的文件。我认为相关的代码片段如下:

class track_transfer:
    def __init__(self, size, fname):
        self.file_name=fname
        self.size_in_bytes=size
        self.downloaded=0
        self.file=open(fname, 'wb')

    def __del__(self):
        try:
            self.file.close()
            self.file=None
        except:
            pass

    def update(self):
        self.downloaded=self.file.tell()
        if self.downloaded==self.size_in_bytes:
            self.file.close()

如您所见,我尝试在两个地方关闭文件:一个在终结器中,另一个在类方法update()中。
我想知道的是当我使用这个类时我的文件会正确关闭吗?
还是有更好的方法可以遵循?

更新
我想我可能需要在这里提供更多信息。

track_transfer有另一个名为progress(self, data)的方法,定义如下:

    def progress(self, data):
        self.file.write(data)
        self.update()

实例化类添加了更多信息,

tracker=track_transfer(size=fsize, fname=fname)

并下载文件,

ftp.retrbinary("RETR %s" %(fname),
        callback=tracker.progress)

其中 ftp.retrbinary() 是ftplib库中定义的一种方法,用于从 ftp 服务器检索二进制文件。每当接收到数据块时,这将调用跟踪器objetc 的进度方法。这意味着在下载文件时会多次调用progress()方法。

标签: pythonpython-2.7classpython-multiprocessingftplib

解决方案


__del__可能没有帮助:它只会在实例被垃圾收集时调用,track_transfer并且它可能是唯一引用文件的东西 - 所以文件无论如何都会被垃圾收集,Python 将关闭当该对象被垃圾收集时文件。(__del__ 适用于您可能不会遇到的非常特殊用途的情况;Python 自然是一种垃圾收集语言,因此我们通常不会为“析构函数”之类的东西烦恼。)

管理文件对象生命周期的常规方法是使用with块:

with open(path, mode) as f:
    # do file operations
# file will be closed when the block is exited, even if by an exception etc.

这是有效的,因为文件是它自己的“上下文管理器”。将文件存储为类属性与这种方法不太吻合,因为您希望在一个类方法调用中打开文件并在稍后关闭它。但是我们可以通过使我们的类成为上下文管理器并使用它的上下文管理而不是文件来解决这个问题。


推荐阅读