open loads how extension example datacamp python pickle

python - how - pickle.loads example



Python decapado después de cambiar el directorio de un módulo (4)

Recientemente cambié el diseño del directorio de mi programa: antes, tenía todos mis módulos dentro de la carpeta "principal". Ahora, los moví a un directorio que lleva el nombre del programa y coloqué un __init__.py allí para hacer un paquete.

Ahora tengo un solo archivo .py en mi directorio principal que se usa para iniciar mi programa, que es mucho más limpio.

De todos modos, el intento de cargar en archivos decapados de versiones anteriores de mi programa está fallando. Recibo "ImportError: No hay un módulo llamado herramientas", lo que supongo que se debe a que mi módulo se encontraba anteriormente en la carpeta principal, y ahora está en whyteboard.tools, no simplemente en herramientas simples. Sin embargo, el código que se está importando en el módulo de herramientas se encuentra en el mismo directorio que él, por lo que dudo que sea necesario especificar un paquete.

Entonces, mi directorio de programas se ve algo como esto:

whyteboard-0.39.4

-->whyteboard.py

-->README.txt

-->CHANGELOG.txt

---->whyteboard/

---->whyteboard/__init__.py

---->whyteboard/gui.py

---->whyteboard/tools.py

whyteboard.py lanza un bloque de código desde whyteboard / gui.py, que activa la GUI. Este problema de decapado definitivamente no estaba ocurriendo antes de la reorganización del directorio.


Como dicen los documentos de Pickle , para guardar y restaurar una instancia de clase (en realidad también una función), debe respetar ciertas restricciones:

pickle puede guardar y restaurar instancias de clase de forma transparente, sin embargo, la definición de la clase debe ser importable y vivir en el mismo módulo que cuando se almacenó el objeto

whyteboard.tools no es el "mismo módulo que las tools " (aunque puede importarse mediante import tools con otros módulos en el mismo paquete, termina en sys.modules como sys.modules[''whyteboard.tools''] : esto es absolutamente crucial, de lo contrario, el mismo módulo importado por uno en el mismo paquete versus uno en otro paquete terminaría con entradas múltiples y posiblemente conflictivas.).

Si sus archivos de pickle están en un formato bueno / avanzado (a diferencia del formato antiguo ascii, que es el predeterminado solo por razones de compatibilidad), migrarlos una vez que realice dichos cambios puede no ser tan trivial como "editar el archivo" ( que es binario & c ...!), a pesar de lo que sugiere otra respuesta. Sugiero que, en cambio, hagas un pequeño "script de migración de pickle": déjalo parchear a sys.modules como este ...

import sys from whyteboard import tools sys.modules[''tools''] = tools

y luego cPickle.load cada archivo, del sys.modules[''tools''] , y cPickle.dump cada objeto cargado de nuevo en el archivo: esa entrada adicional temporal en sys.modules debería permitir que los pickles se carguen con éxito, luego debe sys.modules nuevamente. usar el nombre de módulo correcto para las clases de las instancias (eliminar esa entrada adicional debería asegurarse de ello).


Este es el comportamiento normal de pickle, los objetos no seleccionados deben tener su módulo de definición importable .

Debería poder cambiar la ruta de los módulos (es decir, de las tools a whyteboard.tools ) editando los archivos encurtidos, ya que normalmente son archivos de texto simples.


Me sucedió, lo resolví agregando la nueva ubicación del módulo a sys.path antes de cargar pickle:

import sys sys.path.append(''path/to/whiteboard'') f = open("pickled_file", "rb") pickle.load(f)


pickle serializa las clases por referencia, por lo que si cambias la vida de la clase, no se deshará porque la clase no se encontrará. Si usa dill lugar de pickle , entonces puede serializar clases por referencia o directamente (serializando directamente la clase en lugar de su ruta de importación). Puede simular esto con bastante facilidad simplemente cambiando la definición de clase después de un dump y antes de una load .

Python 2.7.8 (default, Jul 13 2014, 02:29:54) [GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import dill >>> >>> class Foo(object): ... def bar(self): ... return 5 ... >>> f = Foo() >>> >>> _f = dill.dumps(f) >>> >>> class Foo(object): ... def bar(self, x): ... return x ... >>> g = Foo() >>> f_ = dill.loads(_f) >>> f_.bar() 5 >>> g.bar(4) 4