2010-11-09 1 views
2

J'ai essayé de décoller certains dictionnaires de la base de données. Je suis retourné à l'utilisation du module marshal, mais je me demandais toujours pourquoi le pickle avait du mal à désérialiser certaines données. Voici une ligne de commande montrant session de python essentiellement ce que je suis en train de faire:Python pickle semble rompre à l'intérieur de la classe, mais pas dans le script de la ligne de commande

>>> a = {'service': 'amazon', 'protocol': 'stream', 'key': 'lajdfoau09424jojf.flv'} 
>>> import pickle; import base64 
>>> pickled = base64.b64encode(pickle.dumps(a)) 
>>> pickled 
'KGRwMApTJ3Byb3RvY29sJwpwMQpTJ3N0cmVhbScKcDIKc1Mna2V5JwpwMwpTJ2xhamRmb2F1MDk0MjRqb2pmLmZsdicKcDQKc1Mnc2VydmljZScKcDUKUydhbWF6b24nCnA2CnMu' 
>>> unpickled = pickle.loads(base64.b64decode(pickled)) 
>>> unpickled 
{'protocol': 'stream', 'service': 'amazon', 'key': 'lajdfoau09424jojf.flv'} 
>>> unpickled['service'] 
'amazon' 

Cela fonctionne très bien, mais quand j'essaie ceci à l'intérieur d'une méthode de fabrication pour une classe, il semble que la partie de pickle.loads erreurs sur. Les cordes que j'essaie de charger sont marinés de la même manière que ci-dessus. J'ai même essayé de copier la chaîne exacte qui est décapée dans la session de ligne de commande ci-dessus et j'essaie juste de la décoder, mais sans succès. Voici le code de cette dernière tentative:

class Resource: 

    _service = 'unknown' 
    _protocol = 'unknown' 
    _key = 'unknown' 

    ''' 
    Factory method that creates an appropriate instance of one of Resource’s subclasses based on 
    the type of data provided (the data being a serialized dictionary with at least the keys 'service', 
    'protocol', and 'key'). 
    @param resource_data (string) -- the data used to create the new Resource instance. 
    ''' 
    @staticmethod 
    def resource_factory(resource_data): 
     # Unpack the raw resource data and then create the appropriate Resource instance and return. 
     resource_data = "KGRwMApTJ3Byb3RvY29sJwpwMQpTJ3N0cmVhbScKcDIKc1Mna2V5JwpwMwpTJ2xhamRmb2F1MDk0MjRqb2pmLmZsdicKcDQKc1Mnc2VydmljZScKcDUKUydhbWF6b24nCnA2CnMu" #hack to just see if we can unpickle this string 
     logging.debug("Creating resource: " + resource_data) 
     unencoded = base64.b64decode(resource_data) 
     logging.debug("Unencoded is: " + unencoded) 
     unpacked = pickle.loads(unencoded) 
     logging.debug("Unpacked: " + unpacked) 
     service = unpacked['service'] 
     protocol = unpacked['protocol'] 
     key = unpacked['key'] 

     if (service == 'amazon'): 
      return AmazonResource(service=service, protocol=protocol, key=key) 
     elif (service == 'fs'): 
      return FSResource(service=service, protocol=protocol, key=key) 

Répondre

0

j'ai pu résoudre ce après avoir fait quelques simplifications et de débogage dans django. Le principal problème était qu'il y avait des erreurs dans la classe Resource elle-même qui empêchaient l'achèvement correct de la méthode resource_factory. D'abord, j'essayais de concaténer une chaîne et un dictionnaire, ce qui était une erreur. J'ai également eu des erreurs ailleurs dans la classe où je faisais référence aux variables d'instance _service, _protocol, et avec la clé '' (fautes de frappe). En tout cas, ce qui est intéressant, c'est que lorsque j'utilise ce code dans l'infrastructure de terrain personnalisée de Django, les erreurs sont interceptées et je ne vois aucun message indiquant le problème. Les instructions de débogage suggéraient que c'était un problème avec les charges, mais en fait c'était un problème avec l'instruction de débogage elle-même et du code qui est venu plus tard. Lorsque j'ai essayé d'implémenter ce comportement en utilisant des propriétés de modèle au lieu de champs de modèle personnalisés pour les données que je sauvegardais, les erreurs ont été correctement imprimées et j'ai pu déboguer rapidement.

0

Votre code fonctionne. Comment le testez-vous?

import logging 
import base64 
import pickle 
class Resource: 
    @staticmethod 
    def resource_factory(resource_data): 
     resource_data = "KGRwMApTJ3Byb3RvY29sJwpwMQpTJ3N0cmVhbScKcDIKc1Mna2V5JwpwMwpTJ2xhamRmb2F1MDk0MjRqb2pmLmZsdicKcDQKc1Mnc2VydmljZScKcDUKUydhbWF6b24nCnA2CnMu" #hack to just see if we can unpickle this string 
     # logging.debug("Creating resource: " + resource_data) 
     unencoded = base64.b64decode(resource_data) 
     # logging.debug("Unencoded is: " + unencoded) 
     unpacked = pickle.loads(unencoded) 
     logging.debug("Unpacked: " + repr(unpacked)) 
     service = unpacked['service'] 
     protocol = unpacked['protocol'] 
     key = unpacked['key'] 

logging.basicConfig(level=logging.DEBUG) 
Resource.resource_factory('') 

cède

# DEBUG:root:Unpacked: {'protocol': 'stream', 'service': 'amazon', 'key': 'lajdfoau09424jojf.flv'} 
+0

Je cours cela sous un environnement django en utilisant apache mod_wsgi. Peut-être y a-t-il un problème avec cela? C'est vraiment étrange car la session shell ci-dessus se fait dans le même environnement django (shell python manage.py). Le problème se produit lorsque vous essayez d'effectuer les recherches à partir de la base de données (j'utilise la classe Resource pour piloter un champ de modèle spécial dans Django qui lit à partir d'une colonne db où les données sérialisées sont conservées). – Faisal

Questions connexes