Me pregunto si hay una manera de cargar un objeto que se encurtió en Python 2.4, con Python 3.4.
He estado ejecutando 2to3 en una gran cantidad de código heredado de la compañía para actualizarlo.
Una vez hecho esto, cuando ejecuto el archivo aparece el siguiente error:
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)
Mirando el objeto encurtido en disputa, es un dict
en a dict
, que contiene claves y valores de tipo str
.
Entonces mi pregunta es: ¿hay alguna forma de cargar un objeto, originalmente en escabeche en Python 2.4, con Python 3.4?
json
módulo? Tal vez podría escribir un script 2.4 que desenrede el objeto y lo guarde como un objeto json, y luego escribir un script 3.4 que lea el objeto json y lo guarde como un objeto pickle compatible con 3.4. Esta sería una operación de una sola vez que ejecuta en todos sus archivos pickle.Respuestas:
Tendrá que indicar
pickle.load()
cómo convertir los datos de la cadena de bytes de Python en cadenas de Python 3, o puede indicarpickle
que los deje como bytes.El valor predeterminado es intentar decodificar todos los datos de cadena como ASCII, y esa decodificación falla. Ver la
pickle.load()
documentación :Configurar la codificación le
latin1
permite importar los datos directamente:pero deberá verificar que ninguna de sus cadenas esté decodificada usando el códec incorrecto; Latin-1 funciona para cualquier entrada ya que asigna los valores de byte 0-255 a los primeros 256 puntos de código Unicode directamente.
La alternativa sería cargar los datos con
encoding='bytes'
, y decodificar todas lasbytes
claves y valores después.Tenga en cuenta que hasta las versiones de Python anteriores a 3.6.8, 3.7.2 y 3.8.0, el desbloqueo de los
datetime
datos del objeto Python 2 está roto a menos que lo useencoding='bytes'
.fuente
encoding
palabra clave por completo para Python 2.'encoding': 'latin1'
y enviar ** pickle_options a pickle. De esta manera debería ejecutarse en ambas versiones.datetime
comentario no fue el objetivo principal de esta respuesta, pero para los futuros lectores, me gustaría señalar que incluso las versiones "fijas" de Python 3 todavía requierenencoding='latin-1'
que las fechas de Python 2 no estén disponibles. Si los datos en escabeche de Python 2 incluyen fechas y cadenas de bytes codificadas en algo que no sea Latin-1, entonces es mejor que lo useencoding='bytes'
después de todo.El uso
encoding='latin1'
causa algunos problemas cuando su objeto contiene matrices numpy en él.Usar
encoding='bytes'
será mejor.Consulte esta respuesta para obtener una explicación completa del uso
encoding='bytes'
fuente
bytes
hace cadenas en bytes (), así que prefierolatin1
si es posible, pero no me queda claro cuál es el problema.numpy.ndarray
(numpy 1.14) en escabeche en Python 2.7 usandocPickle.dumps()
, y desbocando en Python 3 conpickle.loads(..., encoding='latin1')
buen funcionamiento.