Cómo recuperar una clase en escabeche y sus instancias.

Me gustaría almacenar una clase y muchas instancias para su uso posterior, o para dar a otra persona.

Hasta el momento, puedo descifrar y recuperar las instancias, pero tengo que recrear la clase a mano antes de cargarlas.

He visto esta documentación que me lleva a creer que debería poder hacer esto de alguna manera, pero parece que no puedo encontrar exactamente cómo hacerlo.

EDITAR: He leído esta respuesta discutiendo el uso de dill (vea también esta respuesta), pero no tengo el dill instalado. Me gustaría una solución de salmuera si existe.

 import numpy as np import pickle class wow(object): def __init__(self, x): self.x = x w5 = wow(np.arange(5)) w3 = wow(range(3)) with open("w5w3.pickle", "w") as outfile: pickle.dump([w5, w3], outfile) # save the class also with open("wow.pickle", "w") as outfile: pickle.dump(wow, outfile) # OK, now delete class wow, then try to recover the pickles del wow, w3, w5 try: with open("wow.pickle", "r") as infile: wow = pickle.load(infile) except Exception, e: # returns: "'module' object has no attribute 'wow'" print str(e) print "so manually recreate class wow" class wow(object): def __init__(self, x): self.x = x with open("w5w3.pickle", "r") as infile: W = pickle.load(infile) for thing in W: print type(thing.x), thing.x 

Creo que el error se debe a que eliminó la definición de clase. La serialización de objetos en Python (que, según mi conocimiento, también está en Java) requiere que la definición de clase esté allí.

De su documentación enlazada:

Tenga en cuenta que las funciones (incorporadas y definidas por el usuario) se seleccionan por referencia de nombre “completamente calificado”, no por valor. Esto significa que solo el nombre de la función está decapado, junto con el nombre del módulo en el que se define la función. Ni el código de la función, ni ninguno de sus atributos de función están decapados. Por lo tanto, el módulo de definición debe ser importable en el entorno de despeje, y el módulo debe contener el objeto nombrado, de lo contrario se generará una excepción. [4]

De manera similar, las clases se declinan por referencia nombrada, por lo que se aplican las mismas restricciones en el entorno de descifrado. Tenga en cuenta que ninguno de los datos o el código de la clase está decapado.

Si desea enviar a su amigo la clase y las instancias, envíe la clase a través de un código que defina la clase wow , y las instancias a través del archivo pickle.

Por lo general, puedes encurtir cualquier objeto si puedes encurtir cada atributo de ese objeto. Las clases, funciones y métodos no pueden ser decapados .

Fuente: https://wiki.python.org/moin/UsingPickle

No destruya la clase ni la importe como un módulo.

Si le preocupa la seguridad, tanto dill como pickle tienen los mismos problemas. Sin embargo, si desea facilidad de uso, dill encarga del caso exacto que desea manejar. Puede crear una clase dinámicamente y luego guardarla con dill … luego pasar la instancia a un entorno que no tenga la definición de la clase, y dill aún podrá recrear la clase y la instancia de la clase. Esto se debe a que, a diferencia de pickle , dill almacena la definición de la clase en el pickle (de forma predeterminada), así como el estado de la instancia de la clase.

 >>> class Foo(object): ... x = 1 ... def bar(self, y): ... return self.x + y ... def __init__(self, z): ... self.z = z ... >>> f = Foo(2) >>> import dill >>> with open('instance.pkl', 'w') as pkl: ... dill.dump(f, pkl) ... >>> 

Luego envíe el archivo a otra computadora … reinicie una sesión, y como magia, funciona.

 Python 2.7.10 (default, Sep 2 2015, 17:36:25) [GCC 4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.40)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import dill >>> with open('instance.pkl', 'r') as pkl: ... f = dill.load(pkl) ... >>> f <__main__.Foo object at 0x10eb4a450> >>> fx 1 >>> fz 2 >>> print dill.source.getsource(f.__class__) class Foo(object): x = 1 def bar(self, y): return self.x + y def __init__(self, z): self.z = z >>> 

En resumen, no estoy de acuerdo con todas las otras respuestas. Incluso ha vinculado una respuesta en su pregunta que muestra que las instancias de clase, el estado de la instancia de clase y el código de clase pueden ser encurtidos. Pickle python class instance plus definition

debe abrir el archivo pickle en modo binario como se menciona aquí :

 with open('data.pickle', 'wb') as f: pickle.dump(data, f)