Recientemente he cambiado mi directorio del programa de diseño: antes, yo tenía toda mi módulos dentro de la «principal» de la carpeta. Ahora, que me he movido en un directorio con el nombre del programa, y se coloca un __init__.py allí para hacer un paquete.

Ahora tengo una sola .py archivo en mi directorio principal que se utiliza para el lanzamiento de mi programa, que es mucho más limpio.

De todos modos, tratando de carga en escabeche archivos de versiones anteriores de mi programa está fallando. Estoy recibiendo, «ImportError: No module named herramientas» -, lo cual supongo que es porque mi módulo fue previamente en la carpeta principal, y ahora está en whyteboard.herramientas, no simplemente en la llanura de herramientas. Sin embargo, el código que se importen en el módulo de herramientas de vidas en el mismo directorio como ella, así que dudo que haya una necesidad de especificar un paquete.

Por 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 activa la interfaz gráfica de usuario. Esta decapado problema definitivamente no estaba sucediendo antes de que el directorio de la re-organización.

  • tal vez usted puede agregar el módulo de pythonpath (sys.path.append(path_to_your_module)) antes de la salmuera de carga?

5 Comentarios

  1. 64

    Como pepinillo del docs decir, en el fin de salvar y restaurar una instancia de una clase (en realidad, una función, también), se debe respetar ciertas restricciones:

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

    whyteboard.tools es no el «el mismo módulo de» tools (aunque puede ser importado por import tools por 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 vs uno en otro paquete acabaría con múltiples y posiblemente contradictorias entradas!).

    Si su pickle archivos están en un buen/formato avanzado (a diferencia del antiguo formato ascii que es el valor predeterminado sólo por razones de compatibilidad), la migración de una vez de realizar este tipo de cambios pueden, de hecho, no ser tan trivial como «editar el archivo» (que es un binario &c…!), a pesar de lo que otra respuesta sugiere. Sugiero que, en su lugar, hacer un poco de «pickle-migración de secuencia de comandos»: dejar que el parche sys.modules como esta…:

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

    y, a continuación, cPickle.load cada archivo, del sys.modules['tools'], y cPickle.dump cada objeto cargado de nuevo a file: temporal adicional de entrada en sys.modules debe permitir que los encurtidos se carga correctamente, luego dejarlos de nuevo en caso de estar utilizando el derecho de módulo nombre para las instancias de clases (la eliminación de la extra de entrada debe asegurarse de que).

    • Lo he probado pero ¿por qué no es trabajo para mí? :/
    • El Dumping después de la eliminación de la sys.los módulos de entrada no funciona. Se da el error de Can't pickle ya que el módulo es la que falta. Hay algo que me falta?
  2. 11

    Me pasó a mí, resuelto por la adición de la nueva ubicación del módulo sys.ruta de acceso antes de la carga de la salmuera:

    import sys
    sys.path.append('path/to/whiteboard')
    f = open("pickled_file", "rb")
    pickle.load(f)
    • ¿cuál es el valor de f ?
  3. 7

    Esto se puede hacer con un custom «unpickler» que utiliza find_class():

    import io
    import pickle
    
    
    class RenameUnpickler(pickle.Unpickler):
        def find_class(self, module, name):
            renamed_module = module
            if module == "tools":
                renamed_module = "whyteboard.tools"
    
            return super(RenameUnpickler, self).find_class(renamed_module, name)
    
    
    def renamed_load(file_obj):
        return RenameUnpickler(file_obj).load()
    
    
    def renamed_loads(pickled_bytes):
        file_obj = io.BytesIO(pickled_bytes)
        return renamed_load(file_obj)

    Entonces usted tendría que usar renamed_load() en lugar de pickle.load() y renamed_loads() en lugar de pickle.loads().

    • Tal vez el viejo, pero gracias por esto. Yo tenía una verdadera headscratcher cuando yo tenía un problema similar.
    • Gracias por publicar esta solución. Funciona con Python 3.7.x. Este ahorrado un montón de trabajo. Mientras que la solución publicado por Rancho funciona lo suficientemente bien como para leer clases de «fuera de lugar» de los módulos, esta solución permite un control programático Y la conversión de tales,
  4. 5

    Este es el comportamiento normal de la salmuera, unpickled objetos necesitan tener su la definición de módulo de importables.

    Usted debería ser capaz de cambiar los módulos de ruta (es decir, de tools a whyteboard.tools) editando el escabeche de archivos, ya que normalmente son archivos de texto simple.

  5. 5

    pickle serializa clases por referencia, por lo que si cambio la vida de la clase, no unpickle porque la clase no se encontró. Si utiliza dill en lugar de pickle, entonces usted puede serializar clases por referencia o directamente (directamente a serializar la clase en lugar de la ruta de importación). Usted simular esta muy fácilmente, tan solo cambiando la definición de la clase después de un dump y antes de un 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

Dejar respuesta

Please enter your comment!
Please enter your name here