загрузите файл рассола из zipfile

По некоторым причинам я не могу заставить cPickle.load работать над объектом типа файла, возвращенным ZipFile.open (). Если я называю чтение () на объекте типа файла возвращенным ZipFile.open (), я могу использовать cPickle.loads все же.

Пример....

import zipfile
import cPickle

# the data we want to store
some_data = {1: 'one', 2: 'two', 3: 'three'}

#
# create a zipped pickle file
#
zf = zipfile.ZipFile('zipped_pickle.zip', 'w', zipfile.ZIP_DEFLATED)
zf.writestr('data.pkl', cPickle.dumps(some_data))
zf.close()

#
# cPickle.loads works
#
zf = zipfile.ZipFile('zipped_pickle.zip', 'r')
sd1 = cPickle.loads(zf.open('data.pkl').read())
zf.close()

#
# cPickle.load doesn't work
#
zf = zipfile.ZipFile('zipped_pickle.zip', 'r')
sd2 = cPickle.load(zf.open('data.pkl'))
zf.close()

Примечание: Я не хочу архивировать просто файл рассола, но много файлов других типов. Это - просто пример.

6
задан eric.frederich 9 June 2010 в 14:22
поделиться

1 ответ

Это связано с несовершенством объекта псевдофайла, реализованного модулем zipfile (для метода .open класса ZipFile , представленного в Python 2.6). . Рассмотрим:

>>> f = zf.open('data.pkl')
>>> f.read(1)
'('
>>> f.readline()
'dp1\n'
>>> f.read(1)
''
>>> 

последовательность .read (1) - .readline () - это то, что внутренне делает .loads (на рассол для протокола 0 , значение по умолчанию в Python 2, которое вы здесь используете). К сожалению, несовершенство zipfile означает, что эта конкретная последовательность не работает, создавая ложный «конец файла» (.read, возвращающий пустую строку) сразу после первой пары чтение / строка чтения.

Не уверен, что эта ошибка в стандартной библиотеке Python исправлена ​​в Python 2.7 - я собираюсь проверить.

Правка : только что проверено - ошибка исправлена ​​в Python 2.7 rc1 (релиз-кандидат, который на данный момент является последней версией 2.7). Я еще не знаю, исправлено ли это в последней версии исправления ошибок 2.6.

Отредактируйте еще раз : ошибка все еще присутствует в Python 2.6.5, последней версии исправления ошибок Python 2.6 - поэтому, если вы не можете выполнить обновление до 2.7 и вам нужны объекты псевдофайлов с улучшенным поведением из ZipFile.open , бэкпорт исправления 2.7 кажется единственным жизнеспособным решением.

Обратите внимание, что нет уверенности, что вам нужны объекты псевдофайлов с лучшим поведением; если вы управляете вызовами дампа и можете использовать самый последний и самый лучший протокол, все будет в порядке:

>>> zf = zipfile.ZipFile('zipped_pickle.zip', 'w', zipfile.ZIP_DEFLATED)
>>> zf.writestr('data.pkl', cPickle.dumps(some_data, -1))
>>> sd2 = cPickle.load(zf.open('data.pkl'))
>>> 

это только старый грубый обратно совместимый «протокол 0» (по умолчанию), который требует правильного поведения объекта псевдофайла при смешивании чтения и вызовы readline в load (протокол 0 также работает медленнее и приводит к увеличению размера огурцов, поэтому это определенно не рекомендуется, кроме случаев обратной совместимости со старыми версиями Python или только ascii-природы солений, создаваемых 0, являются обязательными ограничениями в вашем приложении).

8
ответ дан 16 December 2019 в 21:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: