【问题标题】:Python: memory usage while writing to a file (generator vs list)Python:写入文件时的内存使用情况(生成器与列表)
【发布时间】:2018-09-07 13:38:29
【问题描述】:

我正在尝试从一个大型 tarball 文件创建文件名列表,我想了解为什么在我的示例中内存使用量仍然相同?是因为f.write() 在文件实际关闭之前仍在内存中保存/缓冲所有对象吗?有什么办法可以改善吗?

# touch file{1..100000}.txt
# tar cf test.tar file*

生成器

# python test.py 
Memory (Before): 40.918MB
Memory (After): 117.066MB
It took 12.636950492858887 seconds.

列表:

# python test.py
Memory (Before): 40.918MB
Memory (After): 117.832MB
It took 12.049121856689453 seconds.

test.py

#!/usr/bin/python3

import memory_profiler
import tarfile
import time


def files_generator(tar):
    entry = tar.next()
    while entry:
        yield entry.name
        entry = tar.next()

def files_list(tar):
    return tar.getnames()

if __name__ == '__main__':
    print(f'Memory (Before): {memory_profiler.memory_usage()[0]:.3f}MB')
    start = time.time()
    tar = tarfile.open('test.tar')
    with open('output_g.txt', 'w') as f:
        for i in files_generator(tar):
        #for i in files_list(tar):
            f.write(i + '\n')
    end = time.time()
    print(f'Memory (After): {memory_profiler.memory_usage()[0]:.3f}MB')
    print(f'It took {end-start} seconds.')

【问题讨论】:

  • 你试过刷盘吗?

标签: python list memory-management generator


【解决方案1】:

Tarfile.next() 方法缓存其内容,including the lines:

if tarinfo is not None: 
    self.members.append(tarinfo)

事实证明Tarfile.getnames() 调用Tarfile.getmembers(),后者调用Tarfile._load(),后者反复调用Tarfile.next(),直到所有内容都被读入self.members。所以Tarfile.getnames() 和通过Tarfile.next() 迭代将有相同的内存使用。

【讨论】:

  • @HTF:如果您想解决此问题,请使用子类覆盖 Tarfile.next() 方法并阻止其缓存。只需从现有类中的方法复制代码并省略违规行。请注意,这将完全破坏Tarfile,除了您的预期用途(因为一切都使用next())。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-10
  • 1970-01-01
  • 2017-12-13
  • 2013-05-05
  • 1970-01-01
相关资源
最近更新 更多