2017-10-20 37 views
0

J'ai une structure décapée composée de primitives intégrées imbriquées (liste, dictionnaires) et d'instances de classes qui ne sont plus dans le projet, qui provoquent donc des erreurs lors du décyptage. Je ne me soucie pas vraiment de ces objets, j'aimerais pouvoir extraire des valeurs numériques stockées dans cette structure imbriquée. Existe-t-il un moyen de décoller un fichier et de remplacer tout ce qui a été cassé en raison de problèmes d'importation avec, disons, None?Comment remplacer des objets provoquant des erreurs d'importation par None pendant la charge de pickle?

je tentais d'hériter de Unpickler et passer outre find_class(self, module, name) retourner Dummy si la classe ne peut pas être trouvé, mais pour une raison que je continue à me TypeError: 'NoneType' object is not callable dans load reduce après.

class Dummy(object): 
    def __init__(self, *argv, **kwargs): 
     pass 

J'ai essayé quelque chose comme

class RobustJoblibUnpickle(Unpickler): 
    def find_class(self, _module, name): 
     try: 
      super(RobustJoblibUnpickle, self).find_class(_module, name) 
     except ImportError: 
      return Dummy 
+0

Voulez-vous dire que vous pourriez pickle un objet mais ne le décuple pas? Quelle est la tâche plus large ici? – roganjosh

+0

@roganjosh cette structure (listes de dicts de listes ..) a été décapée il y a un certain temps et la base de code a changé de façon significative depuis; Maintenant, si j'essaye de le décocher, je suis confronté à des erreurs d'importation, car il n'y a pas de classes comme celles-là, bien que je n'aie pas besoin d'objets stockés ici, ça irait même avec des valeurs numériques et des chaînes seulement; donc, oui, le grand problème est que je ne peux pas le décoder –

Répondre

0

Peut-être que vous pouvez intercepter l'exception dans un bloc try, et faire ce que vous voulez ( défini un objet à None utiliser une classe factice)?

modifier:

Jetez un oeil à cela, je ne sais pas si elle est la bonne façon de le faire, mais il semble bien fonctionner:

import sys 
import pickle 

class Dummy: 
    pass 

class MyUnpickler(pickle._Unpickler): 
    def find_class(self, module, name): # from the pickle module code but with a try 
     # Subclasses may override this. # we are doing it right now... 
     try: 
      if self.proto < 3 and self.fix_imports: 
       if (module, name) in _compat_pickle.NAME_MAPPING: 
        module, name = _compat_pickle.NAME_MAPPING[(module, name)] 
       elif module in _compat_pickle.IMPORT_MAPPING: 
        module = _compat_pickle.IMPORT_MAPPING[module] 
      __import__(module, level=0) 
      if self.proto >= 4: 
       return _getattribute(sys.modules[module], name)[0] 
      else: 
       return getattr(sys.modules[module], name) 
     except AttributeError: 
      return Dummy 

# edit: as per Ben suggestion an even simpler subclass can be used 
# instead of the above 

class MyUnpickler2(pickle._Unpickler): 
    def find_class(self, module, name): 
     try: 
      return super().find_class(module, name) 
     except AttributeError: 
      return Dummy 

class C: 
    pass 

c1 = C() 

with open('data1.dat', 'wb') as f: 
    pickle.dump(c1,f) 

del C# simulate the missing class 

with open('data1.dat', 'rb') as f: 
    unpickler = MyUnpickler(f) # or MyUnpickler2(f) 
    c1 = unpickler.load() 

print(c1) # got a Dummy object because of missing class 
+1

bien, vous devez en quelque sorte faire "à l'intérieur" la routine sans pépin pour continuer à décoller après avoir remplacé un objet par "Aucun" –

+0

voir ma réponse éditer. Est-ce que ça marche pour toi? – progmatico

+1

Oui, j'ai essayé quelque chose comme ça, mon problème est probablement ailleurs; si je comprends bien, cela peut être encore plus facile avec 'super(). find_class (self, module, name)' dans le bloc 'try .. catch'. Mais mon problème semble être ailleurs. Merci d'avoir signalé cela, cependant. –