首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >访问类的多处理代理的子类方法

访问类的多处理代理的子类方法
EN

Stack Overflow用户
提问于 2021-04-08 23:06:00
回答 1查看 199关注 0票数 0

我有一个由多进程管理器管理的类。我能够公开它的方法,并且看过关于如何公开它的属性的文章

Accessing an attribute of a multiprocessing Proxy of a class

我想知道如何从托管类的子类属性调用方法,如

代码语言:javascript
复制
from multiprocessing.managers import BaseManager

class TestSubClass:
    def __init__(self):
        self.a = 1
    def set_a(self, a):
        self.a = a

class TestClass:
    def __init__(self):
        self.subclass = TestSubClass()
    def add_to_a(self, b):
        return b + self.subclass.a

class MyManager(BaseManager): pass

MyManager.register('TestClass', TestClass)

if __name__ == '__main__':

    with MyManager() as manager:

        # Creates classes
        t = TestClass()
        mt : TestClass = manager.TestClass()

        # Runs the Exposed add_to_a method
        print (t.add_to_a(2))
        print (mt.add_to_a(2))

        # Runs the subclass method for the regular class
        t.subclass.set_a(2)
        print (t.add_to_a(2))

        # Runs the subclass method for the proxy class (Fails)
        mt.subclass.set_a(2)
        print (mt.add_to_a(2))

与上述链接问题的主要区别在于,我不是试图将子类返回到主进程,而是简单地调用经理进程中的一个子类方法

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-04-18 13:58:53

您需要为您的TestClass定义一个支持属性的代理类。这应该继承NamespaceProxy以支持属性,您必须显式地公开以下方法:

代码语言:javascript
复制
class TestClassProxy(NamespaceProxy):
    _exposed_ = ('__getattribute__', '__setattr__', '__delattr__', 'add_to_a')

    def add_to_a(self, b):
        callmethod = object.__getattribute__(self, '_callmethod')
        return callmethod('add_to_a', args=(b,))

我还建议将TestSubClass重命名为TestContainedClass。尽管在当前的代码中并不重要,但我会将register语句移到if __name__ == '__main__':块中,以便如果该代码被修改为创建进程,那么如果您碰巧在使用spawn创建这些进程的平台上(例如,Windows),那么新创建的进程就不会不必要地执行register语句。不管怎么说都没什么大不了的。

把这一切结合在一起:

代码语言:javascript
复制
from multiprocessing.managers import BaseManager, NamespaceProxy

class TestContainedClass:
    def __init__(self):
        self.a = 1
    def set_a(self, a):
        self.a = a

class TestClass:
    def __init__(self):
        self.subclass = TestContainedClass()
    def add_to_a(self, b):
        return b + self.subclass.a

class MyManager(BaseManager): pass

class TestClassProxy(NamespaceProxy):
    _exposed_ = ('__getattribute__', '__setattr__', '__delattr__', 'add_to_a')

    def add_to_a(self, b):
        callmethod = object.__getattribute__(self, '_callmethod')
        return callmethod('add_to_a', args=(b,))



if __name__ == '__main__':

    MyManager.register('TestClass', TestClass, TestClassProxy)

    with MyManager() as manager:

        # Creates classes
        t = TestClass()
        mt : TestClass = manager.TestClass()

        # Runs the Exposed add_to_a method
        print (t.add_to_a(2))
        print (mt.add_to_a(2))

        # Runs the subclass method for the regular class
        t.subclass.set_a(2)
        print (t.add_to_a(2))

        # Runs the subclass method for the proxy class (Fails)
        mt.subclass.set_a(2)
        print (mt.add_to_a(2))

指纹:

代码语言:javascript
复制
3
3
4
3

但是请注意,最后的结果是3,而不是预期的4。嵌套对象似乎不能很好地与Manager一起工作。见Sharing a complex object between processes?

要使其工作,两个类都必须由代理来表示:

代码语言:javascript
复制
from multiprocessing.managers import BaseManager, NamespaceProxy

class MyManager(BaseManager): pass

class TestContainedClass:
    def __init__(self):
        self.a = 1
    def set_a(self, a):
        self.a = a

class TestContainedClassProxy(NamespaceProxy):
    _exposed_ = ('__getattribute__', '__setattr__', '__delattr__', 'set_a')

    def set_a(self, a):
        callmethod = object.__getattribute__(self, '_callmethod')
        return callmethod('set_a', args=(a,))

class TestClass:
    def __init__(self, subclass):
        self.subclass = subclass
    def add_to_a(self, b):
        return b + self.subclass.a


class TestClassProxy(NamespaceProxy):
    _exposed_ = ('__getattribute__', '__setattr__', '__delattr__', 'add_to_a')

    def add_to_a(self, b):
        callmethod = object.__getattribute__(self, '_callmethod')
        return callmethod('add_to_a', args=(b,))


if __name__ == '__main__':

    MyManager.register('TestContainedClass', TestContainedClass, TestContainedClassProxy)
    MyManager.register('TestClass', TestClass, TestClassProxy)

    with MyManager() as manager:

        # Creates classes
        testContainedClass = manager.TestContainedClass()
        mt : TestClass = manager.TestClass(testContainedClass)

        # Runs the Exposed add_to_a method
        print (mt.add_to_a(2))

        # Runs the subclass method for the proxy class
        mt.subclass.set_a(2)
        print (mt.add_to_a(2))

指纹:

代码语言:javascript
复制
3
4

当然,它会更简单,只需重构原始代码:

代码语言:javascript
复制
from multiprocessing.managers import BaseManager, NamespaceProxy


class TestClass:
    def __init__(self, a):
        self.a = a
    def add_to_a(self, b):
        return b + self.a

class MyManager(BaseManager): pass

class TestClassProxy(NamespaceProxy):
    _exposed_ = ('__getattribute__', '__setattr__', '__delattr__', 'add_to_a')

    def add_to_a(self, b):
        callmethod = object.__getattribute__(self, '_callmethod')
        return callmethod('add_to_a', args=(b,))


if __name__ == '__main__':

    MyManager.register('TestClass', TestClass, TestClassProxy)

    with MyManager() as manager:

        # Creates classes
        t = TestClass(1)
        mt : TestClass = manager.TestClass(1)

        # Runs the Exposed add_to_a method
        print (t.add_to_a(2))
        print (mt.add_to_a(2))

        # Runs the subclass method for the regular class
        t.a = 2
        print (t.add_to_a(2))

        # Runs the subclass method for the proxy class
        mt.a = 2
        print (mt.add_to_a(2))

指纹:

代码语言:javascript
复制
3
3
4
4

或者,如果要使用方法a访问属性set_a,则可以使用默认代理:

代码语言:javascript
复制
from multiprocessing.managers import BaseManager, NamespaceProxy


class TestClass:
    def __init__(self, a):
        self.set_a(a)
    def set_a(self, a):
        self.a = a
    def add_to_a(self, b):
        return b + self.a

class MyManager(BaseManager): pass



if __name__ == '__main__':

    MyManager.register('TestClass', TestClass)

    with MyManager() as manager:

        # Creates classes
        t = TestClass(1)
        mt : TestClass = manager.TestClass(1)

        # Runs the Exposed add_to_a method
        print (t.add_to_a(2))
        print (mt.add_to_a(2))

        # Runs the subclass method for the regular class
        t.set_a(2)
        print (t.add_to_a(2))

        # Runs the subclass method for the proxy class
        mt.set_a(2)
        print (mt.add_to_a(2))
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67012978

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档