Открепление объекта 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