如何在Python多进程Proxy类中访问属性特性?
问题原因
AutoProxy(默认的代理类)会将exposed参数中声明的所有名称都视为方法,哪怕原类中它是@property装饰的属性。当你直接访问shared_object.items时,代理类会把items当作一个方法返回绑定对象;而当你尝试调用items()时,远程调用实际返回的是list对象,自然会触发TypeError: 'list' object is not callable。method_to_typeid仅用于指定远程返回值的代理类型,无法改变代理类对属性的访问逻辑。
解决方案
需要自定义代理类,重写属性访问逻辑,让它能正确识别并处理@property属性。具体步骤:
- 继承
BaseProxy实现自定义代理类,声明需要暴露的方法/属性。 - 重写
__getattr__方法,区分属性和方法的访问逻辑:对于@property属性,直接调用远程方法获取值;对于普通方法,返回可调用的包装函数。 - 在
register时指定proxytype参数为自定义代理类。
修改后代码
from multiprocessing import Process from multiprocessing.managers import BaseManager, BaseProxy class CustomManager(BaseManager): pass class TestClass: def __init__(self): self._items = [] @property def items(self): return self._items def fill_items(self): self._items.append(1) # 自定义代理类,支持@property属性访问 class TestClassProxy(BaseProxy): _exposed_ = ('items', 'fill_items') def __getattr__(self, name): if name == 'items': # 调用远程的items getter,返回共享list代理 return self._callmethod('items') elif name == 'fill_items': # 包装普通方法,支持远程调用 def wrapper(): return self._callmethod('fill_items') return wrapper raise AttributeError(f"'TestClassProxy' object has no attribute '{name}'") if __name__ == "__main__": CustomManager.register( 'TestClass', TestClass, proxytype=TestClassProxy, method_to_typeid={'items': 'list'} ) manager = CustomManager() manager.start() shared_object = manager.TestClass() p = Process(target=shared_object.fill_items) p.start() p.join() print(shared_object.items) # 输出: [1]
补充说明
- 自定义代理类的
_exposed_列表需要和原exposed参数内容一致,确保远程能访问到对应的方法/属性。 method_to_typeid={'items': 'list'}会将远程返回的list包装成共享的ListProxy,确保多进程间的列表操作是同步的。
内容的提问来源于stack exchange,提问作者kristapsm1111
相关产品推荐
相关产品推荐

