Как записать списки «один за другим» в двоичный файл в Python? - PullRequest
1 голос
/ 11 мая 2011

У меня есть кусок кода, который генерирует довольно большие списки в каждой итерации. Чтобы сохранить память, я хочу записывать каждый список в двоичный файл на каждой итерации после того, как список был сгенерирован. Я пробовал это с текстовыми файлами (даже устанавливая параметр "wb" в Linux). «wb», кажется, не имеет никакого эффекта для файла, который будет записан в двоичном или текстовом формате. Более того, написанный файл огромен, и я не хочу этого. Я уверен, что если я смогу написать эти списки в двоичном формате, этот файл будет намного меньше. спасибо

Ответы [ 3 ]

4 голосов
/ 11 мая 2011

Поскольку вы упомянули о необходимости сжимаемости, я бы предложил использовать pickle с модулем gzip для сжатия выходных данных. Вы можете писать и читать свои списки по одному за раз, вот пример того, как:

import gzip, pickle

output = gzip.open('pickled.gz', 'wb', compresslevel=9)

for x in range(10):
     output.write(pickle.dumps(range(10)) + '\n\n')
output.close()

А затем используйте генератор, чтобы вернуть списки по одному:

def unpickler(input):
    partial = []
    for line in input:
        partial.append(line)
        if line == '\n':
            obj = ''.join(partial)
            partial = []
            yield pickle.loads(obj)

input = gzip.open('pickled.gz', 'rb')
for l in unpickler(input):
    print l

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
1 голос
/ 11 мая 2011

Единственное, что поменял флаг 'b', - это то, как выполняются переводы разрыва строки для поддержки Windows.

import pickle
help(pickle.load)
help(pickle.dump)

# seems fairly efficient, taking 200bytes to store [1,2,...,100],
# 2.7kb to store [1,2,...,1000],
# and 29kb to store [1,2,...,10000]:
>>> len(pickle.dumps(list(range(100))))
208
>>> len(pickle.dumps(list(range(1000))))
2752
>>> len(pickle.dumps(list(range(10000))))
29770

#create and store
data = {}
data['myList'] = [i for i in range(100)]
with open('myfile.pickle', 'wb') as f:
    pickle.dump(data, f)

# retrieve
with open('myfile.pickle', 'wb') as f:
    data2 = pickle.load(f)
print(data2)

Обратите внимание, что небезопасно использовать pickle для любых предоставленных пользователем данных.Вам захочется открыть файл, в который вы пишете, в двоичном режиме.

1 голос
/ 11 мая 2011

Вы можете использовать cPickle для сериализации ваших списков и выгрузки результата в файл.

...