Factory method template conflicts using multiprocessing queue

I applied the factory method template to parameterize the base class of the product class:

def factory(ParentClass):
    class Wrapper(ParentClass):
        _attr = "foo"

        def wrapped_method():
            "Do things to be done in `ParentClass`."""
            return _attr

    return Wrapper

I need to share objects Wrapperwith a process created using a module multiprocessingwith multiprocessing.Queue.

Since it multiprocessing.Queueuses Pickleobjects for storage (see the note in the Pickle documentation ) and is Wrappernot defined at the top level, I get the following error:

PicklingError: Can't pickle <class 'Wrapper'>: attribute lookup Wrapper failed

I used the workaround in this answer and I got another error:

AttributeError: ("type object 'ParentClass' has no attribute 'Wrapper'", <main._NestedClassGetter object at 0x8c7fe4c>, (<class 'ParentClass'>, 'Wrapper'))

Is there a solution for sharing such objects between processes?

+4
2

Pickle , , :

class _NestedClassGetter(object):
    """
    From: http://stackoverflow.com/a/11493777/741316
    When called with the containing class as the first argument,
    and the name of the nested class as the second argument,
    returns an instance of the nested class.
    """
    def __call__(self, factory_method, base):
        nested_class = factory_method(base)

        # make an instance of a simple object (this one will do), for which we
        # can change the __class__ later on.
        nested_instance = _NestedClassGetter()

        # set the class of the instance, the __init__ will never be called on
        # the class but the original state will be set later on by pickle.
        nested_instance.__class__ = nested_class
        return nested_instance

__reduce__ :

    def __reduce__(self):
        state = self.__dict__.copy()
        return (_NestedClassGetter(),
                (factory, ParentClass), state,)

@dano .

+1

, , , , , .

Wrapper:

def __reduce__(self):
    r = super(Wrapper, self).__reduce__()
    return (wrapper_unpickler, 
            ((factory, ParentClass, r[0]) + r[1][1:])) + r[2:] 

:

def wrapper_unpickler(factory, cls, reconstructor, *args):
    return reconstructor(*((factory(cls),) + args))

, Wrapper factory funciton + wrapped class , Wrapper ( factory ) Wrapper.

+1

Source: https://habr.com/ru/post/1547777/


All Articles