Распаковка данных, маринованных в Python 2.5, в Python 3.1, а затем распаковка с помощью zlib

В Python 2.5 я сохранял данные, используя этот код:

def GLWriter(file_name, string):
   import cPickle
   import zlib
   data = zlib.compress(str(string))
   file = open(file_name, 'w')
   cPickle.dump(data, file)

Это сработало нормально, я смог прочитать эти данные, выполнив этот процесс в обратном порядке. Это не должно быть безопасным, просто что-то, что не может быть прочитано человеческим глазом. Если я вставил в него «тест», а затем открыл созданный им файл, он выглядел так:

S'x\x9c+I-.\x01\x00\x04]\x01\xc1'
p1
.

По разным причинам сейчас мы вынуждены использовать Python 3.1, и нам нужно написать код, который сможет читать эти файлы данных.

Pickle больше не принимает ввод строки, поэтому мне пришлось открывать файл с помощью «rb». Когда я делаю это и пытаюсь открыть его с помощью pickle.load(file), я получаю эту ошибку:

File "<stdin>", line 1, in <module>
File "C:\Python31\lib\pickle.py", line 1365, in load
   encoding=encoding, errors=errors).load()
UnicodeDecodingError: 'ascii' codec can't decode byte 0x9c in position 1: ordinal not in range(128)

Поняв, что я не смогу открыть файл в pickle, я начал проводить некоторые исследования и обнаружил, что pickle просто оборачивает несколько символов с каждой стороны основного блока данных, который создает zlib. Затем я попытался обрезать его до вывода zlibs и передать его через zlib.decompress. Моя проблема в том, что он читает файл и интерпретирует подобные «\ x04» как четыре символа, а не один. Позже много тестов и поисков, и я не могу найти способ заставить pickle загрузить файл или заставить python распознавать эти коды, чтобы я мог пропустить его через zlib.

Итак, мой вопрос таков: как я могу восстановить исходные данные с помощью Python3.1?

Я бы хотел попросить своих клиентов установить Python 2.5 и сделать это вручную, но это невозможно.

Большое спасибо за вашу помощь!


person David Lugg    schedule 25.11.2010    source источник


Ответы (2)


Проблема в том, что Python 3 пытается преобразовать маринованную строку Python 2 в объект str, когда вам действительно нужно, чтобы он был bytes. Он делает это с помощью кодека ascii, который не поддерживает все 256 8-битных символов, поэтому вы получаете исключение.

Вы можете обойти это, используя кодировку latin-1 (которая поддерживает все 256 символов), а затем кодируя строку обратно в bytes:

s = pickle.load(f, encoding='latin1')
b = s.encode('latin1')
print(zlib.decompress(b))
person interjay    schedule 26.11.2010

Python 3 делает различие между двоичными данными и строками. Pickle нужны двоичные данные, но вы открываете файл как текст. Решение заключается в использовании:

open(file_name, 'wb')
person Julian Stecklina    schedule 24.01.2013