Это связано с несовершенством объекта псевдофайла, реализованного модулем 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, возвращающий пустую строку) сразу после первой пары read / readline.
Not sure offhandесли эта ошибка в стандартной библиотеке Python исправлена в Python 2.7 - я собираюсь проверить.
Edit : только что проверил - ошибка исправлена в 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" (по умолчанию), который требует правильного псевдофайлаПоведение объекта при смешивании вызовов read и readline в load
(протокол 0 также медленнее и приводит к большим значениям pickles, поэтому это определенно не рекомендуется, если только обратная совместимость со старыми версиями Python или характер только для ascii, не равны 0производит, являются обязательными ограничениями в вашем приложении).