泄漏TarInfo对象

2024-05-20 23:21:42 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个Python实用程序,它遍历tar.xz文件并处理每个单独的文件。这是一个15MB的压缩文件,有740MB的未压缩数据。在

在内存非常有限的特定服务器上,程序会因为内存不足而崩溃。我使用objgraph查看创建了哪些对象。结果是,TarInfo实例没有被释放。主回路与此类似:

with tarfile.open(...) as tar:
    while True:
        next = tar.next()
        stream = tar.extractfile(next)
        process_stream()
        iter+=1
        if not iter%1000:
            objgraph.show_growth(limit=10)

输出非常一致:

^{pr2}$

这一直持续到30000个文件都被处理完。在

为了确保,我已经注释掉了创建流并处理它的行。内存使用量保持不变-TarInfo实例被泄露。在

我使用的是python3.4.1,这种行为在Ubuntu、osx和Windows上是一致的。在


Tags: 文件数据对象实例内存objgraph程序实用程序
1条回答
网友
1楼 · 发布于 2024-05-20 23:21:42

看起来这实际上是设计的。TarFile对象维护它包含在members属性中的所有TarInfo对象的列表。每次调用^{},它从存档中提取的TarInfo对象都会添加到列表中:

def next(self):
    """Return the next member of the archive as a TarInfo object, when
       TarFile is opened for reading. Return None if there is no more
       available.
    """
    self._check("ra")
    if self.firstmember is not None:
        m = self.firstmember
        self.firstmember = None
        return m

    # Read the next block.
    self.fileobj.seek(self.offset)
    tarinfo = None
    ... <snip>

    if tarinfo is not None:
        self.members.append(tarinfo)  # <  the TarInfo instance is added to members

当您提取更多项时,members列表将继续增长。这样就可以使用^{}^{}方法,但这对您的用例来说只是一个麻烦。似乎最好的解决方法是在迭代时继续清除members属性(如建议的here):

^{pr2}$

相关问题 更多 >