Открепление объекта Python 2 с Python 3

Мне интересно, есть ли способ загрузить объект, который был засолен в Python 2.4, с помощью Python 3.4.

Я использовал 2to3 для большого количества унаследованного кода компании, чтобы обновлять его.

Сделав это, при запуске файла я получаю следующую ошибку:

  File "H:\fixers - 3.4\addressfixer - 3.4\trunk\lib\address\address_generic.py"
, line 382, in read_ref_files
    d = pickle.load(open(mshelffile, 'rb'))
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 1: ordinal
not in range(128)

глядя на маринованный объект в раздоре, это dict в dict, содержащий ключи и значения типа str,

Итак, мой вопрос: есть ли способ загрузить объект, изначально протравленный в python 2.4, с помощью python 3.4?

2 ответа

Решение

Вам придется сказать pickle.load() как преобразовать данные строки Python в строки Python 3, или вы можете сказать, pickle оставить их как байты.

По умолчанию это попытка декодировать все строковые данные как ASCII, и это декодирование завершается неудачно. Увидеть pickle.load() документация:

Необязательные ключевые аргументы: fix_imports, encoding и errors, которые используются для управления поддержкой совместимости потока pickle, сгенерированного Python 2. Если fix_imports имеет значение true, pickle попытается отобразить старые имена Python 2 на новые имена, используемые в Python 3. кодирование и ошибки сообщают pickle, как декодировать экземпляры 8-битных строк, выбранные Python 2; по умолчанию это ASCII и строгий, соответственно. Кодировка может быть "байтами" для чтения этих 8-битных строковых экземпляров как байтовых объектов.

Установка кодировки в latin1 позволяет напрямую импортировать данные:

with open(mshelffile, 'rb') as f:
    d = pickle.load(f, encoding='latin1') 

но вам нужно убедиться, что ни одна из ваших строк не была декодирована с использованием неправильного кодека; Latin-1 работает для любого ввода, так как он напрямую отображает значения байтов 0-255 в первые 256 кодовых точек Unicode.

Альтернативой было бы загрузить данные encoding='bytes'и декодировать все bytes ключи и значения потом.

Использование encoding = 'latin1' вызывает некоторые проблемы, когда ваш объект содержит в себе пустые массивы.

Использование encoding = bytes будет лучше.

Пожалуйста, смотрите этот ответ для полного объяснения использования encoding = bytes

Другие вопросы по тегам