2010-01-23 7 views
23

he cambiado recientemente el diseño del directorio de mi programa: antes, que tenía todas mis módulos dentro de la carpeta "principal". Ahora, los he movido a un directorio que lleva el nombre del programa y coloqué un __init__.py allí para hacer un paquete.Python decapado después de cambiar el directorio de un módulo de

ahora tengo un solo archivo .py en mi directorio principal que se utiliza para poner en marcha mi programa, que es mucho más ordenado.

De todos modos, tratando de cargar archivos en escabeche de versiones anteriores de mi programa está fallando. Me aparece "ImportError: ningún módulo llamado Tools", lo que supongo es porque mi módulo estaba previamente en la carpeta principal, y ahora está en whyteboard.tools, no simplemente en herramientas simples. Sin embargo, el código que está importando en el módulo de herramientas vive en el mismo directorio, por lo que dudo que sea necesario especificar un paquete.

lo tanto, mi directorio del programa 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 de Whyteboard/gui.py, que dispara la interfaz gráfica de usuario. Este problema de decapado definitivamente no estaba ocurriendo antes de la reorganización del directorio.

+0

tal vez usted puede añadir su módulo para PYTHONPATH ('sys.path.append (path_to_your_module) ') antes de la carga de pickle? –

Respuesta

41

Como dicen pickle's docs, con el fin de guardar y restaurar una instancia de clase (en realidad una función, también), se debe respetar ciertas limitaciones:

pickle can save and restore class instances transparently, however the class definition must be importable and live in the same module as when the object was stored

whyteboard.tools es no el "el mismo módulo como" tools (a pesar de que puede ser importado por import tools por otros módulos en el mismo paquete, que 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 contra uno en otro paquete terminaría con entradas múltiples y posiblemente conflictivas!).

Si los archivos de encurtidos están en un buen formato/avanzado (en comparación con el antiguo formato ASCII que es el valor por defecto sólo por razones de compatibilidad), la migración de ellos una vez que la realización de tales cambios pueden, de hecho, no ser tan trivial como "editando el archivo" (que es binario & c ...!), a pesar de lo que sugiere otra respuesta. Sugiero que, en su lugar, hagas un pequeño "script de migración de salmuera": déjalo parchear sys.modules así ...:

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 a archivo: esa entrada adicional temporal en sys.modules debe permitir la carga de las salmueras con éxito, entonces vertido de nuevo se debe usar el nombre-módulo derecho para las clases de instancias (eliminar esa entrada extra debería asegurarse de eso).

+0

Lo he intentado pero [¿por qué no funciona] (http://stackoverflow.com/questions/39944487/pickle-load-importerror-no-module-named-doc2vec-ext) para mí? :/ – displayname

1

Este es el comportamiento normal de la salmuera, objetos unpickled necesitan tener su defining module importable.

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

3

pickle serializa las clases por referencia, por lo que si cambiaste las clases, no se deshace porque la clase no se encontrará. Si usa dill en lugar de pickle, puede serializar las clases por referencia o directamente (serializando directamente la clase en lugar de su ruta de importación). Simular esto bastante fácilmente simplemente cambiando la definición de clase después de dump y antes de 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 
2

me pasó, lo resolvió mediante la adición de la nueva ubicación del módulo de sys.path antes de la carga de la salmuera:

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

¿cuál es el valor de 'f'? – vikkyhacks

Cuestiones relacionadas