2010-01-30 8 views
8

Para evitar el acceso repetido a un servidor SOAP durante el desarrollo, intento almacenar en caché los resultados para poder ejecutar el resto de mi código sin consultar el servidor cada vez.¿Cómo puedo eliminar los resultados de la espuma?

Con el siguiente código obtengo un PicklingError: Can't pickle <class suds.sudsobject.AdvertiserSearchResponse at 0x03424060>: it's not found as suds.sudsobject.AdvertiserSearchResponse cuando trato de extraer un resultado de espuma. Supongo que esto se debe a que las clases se crean dinámicamente.

import pickle 
from suds.client import Client 

client = Client(...) 
result = client.service.search(...) 

file = open('test_pickle.dat', 'wb') 
pickle.dump(result, file, -1) 
file.close() 

Si se me cae la versión -1 protocolo de pickle.dump(result, file, -1), me sale un error diferente:

TypeError: a class that defines __slots__ without defining __getstate__ cannot be pickled 

Está decapado lo que hay que hacer? ¿Puedo hacer que funcione? ¿Hay una mejor manera?

Respuesta

8

Como el mensaje de error que estás recibiendo actualmente está tratando de decir, que estamos tratando de conservar en vinagre instancias que están no estibables (en el antiguo protocolo legado salmuera ahora se está utilizando) porque su clase define __slots__ pero no es un método __getstate__.

Sin embargo, incluso alterar su clase no ayudaría porque entonces se encontraría con el otro problema - que ya identificó correctamente como probable debido a las clases generadas dinámicamente. Todos los protocolos pickle serializan las clases (y funciones) "por nombre", lo que básicamente los limita a estar en los nombres de nivel superior en sus módulos. Y, serializar una instancia absolutamente requiere serializar la clase (¿de qué otra forma podría posiblemente reconstruir la instancia más adelante si la clase no estaba cerca ?!).

Así que tendrá que guardar y volver a cargar sus datos de otra manera, rompiendo su dependencia directa actual de clases concretas en suds.sudsobject a favor de dependiendo de una interfaz (formalizada o simplemente definida por pato) que puede ser implementadas tanto por tales clases concretas cuando de hecho está accediendo al servidor SOAP, o más simples "caseras" cuando está cargando los datos de un archivo. (Los datos que representan el estado de la instancia sin duda se pueden representar como un dict, por lo que puede forzarlo si lo desea, p. Ej. A través del módulo copy_reg que le permite personalizar los protocolos de serialización/deserialización de los objetos que está obligado a tratar de forma no invasiva [[por lo que no puede ir agregando __getstate__ o similar a sus clases]] - el problema vendrá solo si hay una gran cantidad de referencias mutuas entre dichos objetos).

+1

¿Hay alguna forma de obtener la definición de una clase creada dinámicamente para que pueda guardarse en un archivo y luego usarse como una clase normal? – tponthieux

2

Está decapando el objeto de clase en sí, y no los objetos de instancia de la clase. Esto no funcionará si el objeto de la clase es recreado. Sin embargo, las instancias de decapado de la clase funcionarán mientras exista el objeto de clase.

+0

Creo que sigo lo que dices, pero habiendo verificado, escribe (resultado) es y el resultado .__ clase__ es entonces no estoy tratando de saltear la instancia? – Mat

+0

Desde el código pegado, parece que está reduciendo una instancia, pero el error al que se refiere sugiere que está reduciendo una clase. –

+0

Está bien, no me voy a volver del todo loco :) Recibo un error diferente si dejo caer -1 para el protocolo más reciente, que corregiré la pregunta para incluir si deja caer más luz. – Mat

Cuestiones relacionadas