当前位置: 首页 > 面试题库 >

访问类的多处理代理的属性

倪灿
2023-03-14
问题内容

我有一个班级,想与一个池中的子进程以只读方式共享,所以我准备了一个班级的代理,但是没有用。以下是我的问题的简化示例。

from multiprocessing.managers import BaseManager

class TestClass:
    def __init__(self, a):
        self.a = a
    def b(self):
        print self.a

class MyManager(BaseManager): pass

MyManager.register('test', TestClass)

if __name__ == '__main__':
    manager = MyManager()
    manager.start()
    t = TestClass(1)
    print t.a
    mt = manager.test(2)
    mt.b()
    mt.a

当我运行此代码时,我得到:

1
2
Traceback (most recent call last):
  File "multiprocess_example_stackexchange.py", line 20, in <module>
    mt.a 
AttributeError: 'AutoProxy[test]' object has no attribute 'a'

看来我无法直接通过代理访问共享库的属性。是使用获取属性的方法的唯一方法,还是我做错了什么?


问题答案:

通常,由其Proxy使用的对象multiprocessing.BaseManager及其子类仅公开其引用的对象中的 方法
,而不公开属性。现在,这里multiprocessing.Manager().Namespace提供,它提供了一个Proxy子类,该子类 确实
提供对属性而不是方法的访问。我们可以创建自己的Proxy类型,该类型继承自该类型,从而可以访问所有属性以及对b函数的访问:

from multiprocessing.managers import BaseManager, NamespaceProxy

class TestClass(object):
    def __init__(self, a):
        self.a = a

    def b(self):
        print self.a

class MyManager(BaseManager): pass

class TestProxy(NamespaceProxy):
    # We need to expose the same __dunder__ methods as NamespaceProxy,
    # in addition to the b method.
    _exposed_ = ('__getattribute__', '__setattr__', '__delattr__', 'b')

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

MyManager.register('test', TestClass, TestProxy)

if __name__ == '__main__':
    manager = MyManager()
    manager.start()
    t = TestClass(1)
    print t.a
    mt = manager.test(2)
    print mt.a
    mt.a = 5
    mt.b()

输出:

1
2
5

编辑:

如果您希望能够将方法从原始类动态添加到Proxy类,则可以执行以下操作:

from multiprocessing.managers import BaseManager, NamespaceProxy
import inspect

class TestClass(object):
    def __init__(self, a):
        self.a = a

    def b(self):
        print self.a

class AnotherClass(object):
    def __init__(self, a):
        self.a = a

    def c(self):
        print self.a

class MyManager(BaseManager): pass

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

class TestProxy(ProxyBase): pass
class AnotherProxy(ProxyBase): pass


def register_proxy(name, cls, proxy):
    for attr in dir(cls):
        if inspect.ismethod(getattr(cls, attr)) and not attr.startswith("__"):
            proxy._exposed_ += (attr,)
            setattr(proxy, attr, 
                    lambda s: object.__getattribute__(s, '_callmethod')(attr))
    MyManager.register(name, cls, proxy)

register_proxy('test', TestClass, TestProxy)
register_proxy('another', AnotherClass, AnotherProxy)

if __name__ == '__main__':
    manager = MyManager()
    manager.start()
    mt = manager.test(2)
    ma = manager.another(3)
    mt.b()
    ma.c()
    mt.a = 5
    ma.a = 6
    mt.b()
    ma.c()


 类似资料:
  • 问题 你想将某个实例的属性访问代理到内部另一个实例中去,目的可能是作为继承的一个替代方法或者实现代理模式。 解决方案 简单来说,代理是一种编程模式,它将某个操作转移给另外一个对象来实现。 最简单的形式可能是像下面这样: class A: def spam(self, x): pass def foo(self): pass class B1:

  • 关于Anylogic中的批处理过程,我有一个非常简短的问题。 我想打印出已经退出前一个批处理元素的代理的ID,它们是在一起批处理的。因此,它们位于不同的元素(准确地说是发布),我正在努力在批处理中找到它们的ID。我唯一的想法是先取消批处理,然后打印出ID。 有没有一种方法可以在不拆分的情况下做到这一点? 事先非常感谢。 亲切的问候

  • 问题内容: 我想通过多个客户端子进程将数据从客户端发送到TLS TCP套接字中的服务器,因此我与所有子进程共享相同的ssl套接字。通信可以使用一个子进程,但是如果我使用多个子进程,则TLS服务器将崩溃,并显示(SSL3_GET_RECORD:decryption失败或mac记录错误)。 更具体地说: 它不依赖于哪个进程首先调用该方法,但是此进程是此后唯一可以调用该方法的进程。如果另一个进程调用,服

  • 问题内容: 故事: 当您使用解析HTML时,attribute被视为多值属性,并以特殊方式处理: 请记住,单个标签的“ class”属性可以有多个值。当您搜索与某个CSS类匹配的标签时,您将与其任何CSS类进行匹配。 另外,内建的引号用作其他树构建器类的基础,例如: 问题: 如何配置为作为通常的单值属性处理?换句话说,我不希望它专门处理并将其视为常规属性。 我尝试过的 实际上,我通过创建 自定义树

  • 4.2 处理访问违例 当程序尝试访问它们没有权限访问的页面的时候或者以一种不合法的方式访问内存的 时候,就会产生访问违例。导致违例错误的范围很广,从内存溢出到不恰当的处理空指针都 有可能。从安全角度考虑,每一个访问违例都应该仔细的审查,因为它们有可能被利用。 当调试器处理访问违例的时候,需要搜集所有和违例相关的信息,栈框架,寄存器,以及引起违例的指令。接着我们就能够用这些信息写一个利用程序或者创建

  • 我最近提出了这个问题,但我认为我对我的目标不够明确。