Python 多进程代理

1 投票
1 回答
3657 浏览
提问于 2025-04-15 14:39

我有两个进程:

第一个进程是 manager.py,它在后台运行:

from multiprocessing.managers import SyncManager, BaseProxy
from CompositeDict import *

class CompositeDictProxy(BaseProxy):

    _exposed_ = ('addChild', 'setName')
    def addChild(self, child):
        return self._callmethod('addChild', [child])

    def setName(self, name):
        return self._callmethod('setName', [name])

class Manager(SyncManager):
    def __init__(self):
        super(Manager, self).__init__(address=('127.0.0.1', 50000), authkey='abracadabra')

def start_Manager():
    Manager().get_server().serve_forever()

if __name__=="__main__":
    Manager.register('get_plant', CompositeDict, proxytype=CompositeDictProxy)
    start_Manager()

第二个进程是 consumer.py,它应该使用在管理器中定义的注册对象:

from manager import *
import time
import random

class Consumer():

    def __init__(self):
        Manager.register('get_plant')

        m = Manager()
        m.connect()
        plant = m.get_plant()
        #plant.setName('alfa')
        plant.addChild('beta')


if __name__=="__main__":
    Consumer()

当我在后台运行manager,然后再运行consumer时,我遇到了一个错误信息: RuntimeError: maximum recursion depth exceeded,这个错误出现在我在consumer中使用addChild时,而使用setName时却没有问题。

方法addChildsetName属于CompositeDict,我想它们应该是被代理的。

这到底出了什么问题?

CompositeDict重写了原生的__getattr__方法,并且与错误信息有关。我猜测,它在某种程度上没有使用正确的__getattr__方法。如果是这样,我该如何解决这个问题呢?


详细的错误信息是:

Traceback (most recent call last):
  File "consumer.py", line 21, in <module>
    Consumer()
  File "consumer.py", line 17, in __init__
    plant.addChild('beta')
  File "<string>", line 2, in addChild
  File "/usr/lib/python2.5/site-packages/multiprocessing-2.6.1.1-py2.5-linux-i686.egg/multiprocessing/managers.py", line 729, in _callmethod
    kind, result = conn.recv()
  File "/home/--/--/CompositeDict.py", line 99, in __getattr__
    child = self.findChild(name)
  File "/home/--/--/CompositeDict.py", line 185, in findChild
    for child in self.getAllChildren():
  File "/home/--/--/CompositeDict.py", line 167, in getAllChildren
    l.extend(child.getAllChildren())
  File "/home/--/--/CompositeDict.py", line 165, in getAllChildren
    for child in self._children:
  File "/home/--/--/CompositeDict.py", line 99, in __getattr__
    child = self.findChild(name)
  File "/home/--/--/CompositeDict.py", line 185, in findChild
    for child in self.getAllChildren():
  File "/--/--/prove/CompositeDict.py", line 165, in getAllChildren
    for child in self._children:
  ...
  File "/home/--/--/CompositeDict.py", line 99, in __getattr__
    child = self.findChild(name)
  File "/home/--/--/CompositeDict.py", line 185, in findChild
    for child in self.getAllChildren():
  RuntimeError: maximum recursion depth exceeded

1 个回答

1

除了修复上面提到的许多其他错误(我想这些都是意外的,比如init应该写成__init__,你缺少了几个self,还有缩进错误等等),关键是要把manager.py中的注册部分改成:

Manager.register('get_plant', CompositeDict,   proxytype=CompositeDictProxy)

我不太明白你用那个lambda作为第二个参数想干嘛,但第二个参数必须是一个可以调用的东西,它应该能生成你需要的类型,而不是像你现在用的那样生成一个包含两个元素的元组。

撰写回答