Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/344.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/blackberry/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 工厂方法模式与多处理队列的使用冲突_Python_Design Patterns_Multiprocessing - Fatal编程技术网

Python 工厂方法模式与多处理队列的使用冲突

Python 工厂方法模式与多处理队列的使用冲突,python,design-patterns,multiprocessing,Python,Design Patterns,Multiprocessing,我已经实现了factory方法模式来参数化product类的基类: def factory(ParentClass): class Wrapper(ParentClass): _attr = "foo" def wrapped_method(): "Do things to be done in `ParentClass`.""" return _attr return Wrapper 我需要通

我已经实现了factory方法模式来参数化product类的基类:

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

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

    return Wrapper
我需要通过
多处理.Queue
与使用
多处理
模块生成的进程共享
包装
对象

由于
multiprocessing.Queue
使用
Pickle
存储对象(请参见中的注释),并且未在顶层定义
Wrapper
,因此出现以下错误:

PicklingError: Can't pickle <class 'Wrapper'>: attribute lookup Wrapper failed
PicklingError:无法pickle:属性查找包装失败
我在这里使用了解决方法,我得到了另一个错误:

AttributeError: ("type object 'ParentClass' has no attribute 'Wrapper'", <main._NestedClassGetter object at 0x8c7fe4c>, (<class 'ParentClass'>, 'Wrapper'))
AttributeError:(“类型对象'ParentClass'没有属性'Wrapper',(,'Wrapper'))
是否有在进程之间共享此类对象的解决方案?

根据,问题中链接的解决方案可以修改为:

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
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuu
方法:

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

感谢@dano的评论。

最好的解决方案是重新构造代码,使其不具有动态声明的类,但假设不是这样,您可以做更多的工作来pickle它们

将此方法添加到您的
包装器
类:

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))

实际上,在酸洗时,您将动态生成的
包装器
类替换为工厂函数+包装类,然后在取消勾选时,再次动态生成
包装器
类(将包装类型传递给工厂)将包装好的类替换为
包装器

解决方案不起作用,因为
包装器
没有嵌套在
父类
中,它嵌套在
工厂
函数中。但正如我在问题中所说的:我的目标是使用动态声明的类,因为我想使用工厂方法模式。您建议以何种方式构造代码,以获得此模式提供的相同功能?@Kits89这就是为什么我说“但假设情况并非如此”,意思是“假设不可能”。答案的其余部分将为您的问题提供一个有效的解决方案!我只是好奇是否有一个相同的模式。我不想使用动态生成的类。是的,谢谢你的回答,这和我最后想到的差不多(见另一个答案)。谢谢你的帮助:)@Kits89我想我不用额外的导入就可以做到。(参见我的编辑。)在不知道为什么要像现在这样动态创建类的情况下,很难提出替代方案,但在您给出的示例中,
factory
方法可能只包含
setattr(父类,“wrapped\u方法”,wrapped\u方法)
直接将其添加到类中。@Kits89那么您可以将它们直接添加到基类中:
setattr(base,“method\u name”,method)
,在您的测试代码中。