How to use class decorators with pickle?

后端 未结 1 1051
旧巷少年郎
旧巷少年郎 2021-01-16 08:33

I would like to use class decorators (not function decorators!), e.g.

def class_decorator(cls):
    class new_cls(cls):
        def run(self, *args, **kwargs         


        
相关标签:
1条回答
  • 2021-01-16 09:29

    When you pickle a class, the name of the class -- not its value -- is pickled. If the class_decorator returns a new class whose name is not defined at the top level of the module, then you get the error:

    PicklingError: Can't pickle <class '__main__.new_cls'>: it's not found as __main__.new_cls 
    

    You can avoid the error by naming the new decorated class the same as the undecorated class:

    new_cls.__name__ = cls.__name__
    

    Then the code runs without error:

    import pickle
    
    def class_decorator(cls):
        class new_cls(cls):
            def run(self, *args, **kwargs):
                print 'In decorator'
                super(new_cls,self).run(*args, **kwargs)
        new_cls.__name__ = cls.__name__
        return new_cls
    
    @class_decorator
    class cls(object):
        def run(self):
            print 'called'
    
    a = cls()
    print(a)
    # <__main__.cls object at 0x7f57d3743650>
    
    a.run()
    # In decorator
    # called
    
    s = pickle.dumps(a)
    # Note "cls" in the `repr(s)` below refers to the name of the class. This is
    # what `pickle.loads` is using to unpickle the string
    print(repr(s))
    # 'ccopy_reg\n_reconstructor\np0\n(c__main__\ncls\np1\nc__builtin__\nobject\np2\nNtp3\nRp4\n.'
    
    b = pickle.loads(s)
    print(b)
    # <__main__.cls object at 0x7f57d3743690>
    
    b.run()
    # In decorator
    # called
    
    0 讨论(0)
提交回复
热议问题