Python: использование памяти при записи в файл (генератор против списка) - PullRequest
0 голосов
/ 07 сентября 2018

Я пытаюсь создать список имен файлов из большого файла 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.')

1 Ответ

0 голосов
/ 07 сентября 2018

Tarfile.next() метод кэширует свое содержимое, включая строки :

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

Оказывается, что Tarfile.getnames() вызывает Tarfile.getmembers(), который вызывает Tarfile._load(), который многократно вызывает Tarfile.next(), пока все не будет прочитано в self.members. Так что Tarfile.getnames() и итерация по Tarfile.next() будут иметь одинаковое использование памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...