Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ms-access/4.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_Multiprocessing_Python Multiprocessing - Fatal编程技术网

python多处理管理器&;复合模式共享

python多处理管理器&;复合模式共享,python,multiprocessing,python-multiprocessing,Python,Multiprocessing,Python Multiprocessing,我试图通过一个多处理管理器共享一个复合结构,但在尝试仅使用其中一个复合类方法时,我遇到了一个“运行时错误:超过了最大递归深度” 该类是由我创建并测试的,然后才包含到管理器中 在将类检索到进程中并调用其addChild()方法时,我保留了RunTimeError,而在进程之外它可以工作 复合类继承自一个SpecialDisct类,该类实现了**\uuuuuuu getattr()** 方法 调用addChild()时,python的解释器可能会查找不同的**\uuuuuuuuuuuGetAttr(

我试图通过一个多处理管理器共享一个复合结构,但在尝试仅使用其中一个复合类方法时,我遇到了一个“运行时错误:超过了最大递归深度”

该类是由我创建并测试的,然后才包含到管理器中

在将类检索到进程中并调用其addChild()方法时,我保留了RunTimeError,而在进程之外它可以工作

复合类继承自一个SpecialDisct类,该类实现了**\uuuuuuu getattr()** 方法

调用addChild()时,python的解释器可能会查找不同的**\uuuuuuuuuuuGetAttr()\uuuuuuuuuuuuuu**,因为管理器未代理正确的解释器

如果是这样的话,我还不清楚如何为该类/方法创建代理

下面的代码正好再现了这种情况:

1) 这是manager.py:

from multiprocessing.managers import BaseManager
from CompositeDict import *

class PlantPurchaser():

    def __init__(self):
        self.comp  = CompositeDict('Comp')

    def get_cp(self):
        return self.comp

class Manager():

    def __init__(self):

        self.comp  = QueuePurchaser().get_cp()

        BaseManager.register('get_comp', callable=lambda:self.comp)

        self.m = BaseManager(address=('127.0.0.1', 50000), authkey='abracadabra')
        self.s = self.m.get_server()

        self.s.serve_forever()
2) 我想在这个consumer.py中使用组合:

from multiprocessing.managers import BaseManager

class Consumer():

    def __init__(self):

        BaseManager.register('get_comp')

        self.m = BaseManager(address=('127.0.0.1', 50000), authkey='abracadabra')
        self.m.connect()

        self.comp = self.m.get_comp()
        ret = self.comp.addChild('consumer')
3) 通过controller.py运行所有启动:

from multiprocessing import Process

class Controller():
    def __init__(self):
        for child in _run_children():
            child.join()

def _run_children():

    from manager import Manager
    from consumer import Consumer as Consumer

procs = (
         Process(target=Manager,  name='Manager' ),
         Process(target=Consumer, name='Consumer'),
        )

for proc in procs:
    proc.daemon = 1
    proc.start()
return procs

c = Controller()
请看一下如何为CompositeDict()类执行代理 正如阿尔伯特所建议的那样


tgray给出的解决方案可以工作,但无法避免竞争条件

Python的默认最大递归深度为1000(或者999,我忘了…)。但是您可以这样更改默认行为:

import sys
sys.setrecursionlimit(n)
其中
n
是您希望允许的递归数

编辑:

上述答案无法解决此问题的根本原因(如评论中所指出的)。只有在有意递归超过1000次时才需要使用它。如果你在一个无限循环中(就像在这个问题中),你最终会达到你设定的极限

为了解决您的实际问题,我从头开始尽可能简单地重新编写了您的代码,并将其构建为我认为您想要的:

import sys
from multiprocessing import Process
from multiprocessing.managers import BaseManager
from CompositDict import *

class Shared():
    def __init__(self):
        self.comp = CompositeDict('Comp')

    def get_comp(self):
        return self.comp

    def set_comp(self, c):
        self.comp = c

class Manager():
    def __init__(self):
        shared = Shared()
        BaseManager.register('get_shared', callable=lambda:shared)
        mgr = BaseManager(address=('127.0.0.1', 50000), authkey='abracadabra')
        srv = mgr.get_server()
        srv.serve_forever()

class Consumer():
    def __init__(self, child_name):
        BaseManager.register('get_shared')
        mgr = BaseManager(address=('127.0.0.1', 50000), authkey='abracadabra')
        mgr.connect()

        shared = mgr.get_shared()
        comp = shared.get_comp()
        child = comp.addChild(child_name)
        shared.set_comp(comp)
        print comp

class Controller():
    def __init__(self):
        pass

    def main(self):
        m = Process(target=Manager, name='Manager')
        m.daemon = True
        m.start()

        consumers = []
        for i in xrange(3):
            p = Process(target=Consumer, name='Consumer', args=('Consumer_' + str(i),))
            p.daemon = True
            consumers.append(p)

        for c in consumers:
            c.start()
        for c in consumers:
            c.join()
        return 0


if __name__ == '__main__':
    con = Controller()
    sys.exit(con.main())
我在一个文件中完成了这一切,但是你应该不会有任何问题来分解它

我向您的消费者添加了一个
child\u name
参数,以便检查
compositect
是否得到更新

请注意,
compositect
对象既有一个getter,也有一个setter。当我只有一个getter时,每个消费者在添加子项时都覆盖了compositect

这就是为什么我还将您的注册方法更改为
get_shared
,而不是
get_comp
,因为您需要访问Consumer类中的setter和getter

此外,我认为您不想尝试加入您的经理流程,因为它将“永远服务”。如果您查看BaseManager的源代码(./Lib/multiprocessing/managers.py:Line 144),您会注意到
serve\u forever()
函数将您置于一个无限循环中,只有
KeyboardInterrupt
SystemExit
才能打破这个循环


底线是这段代码没有任何递归循环(据我所知),但如果您仍然遇到错误,请告诉我。

类之间是否可能存在循环引用?例如,外部类具有对复合类的引用,而复合类具有对外部类的引用


多处理管理器工作得很好,但是当您拥有大型、复杂的类结构时,可能会遇到类型/引用无法正确序列化的错误。另一个问题是,来自多处理管理器的错误非常隐蔽。这使得调试失败的情况更加困难。

我认为问题在于您必须指导管理器如何管理您的对象,这不是标准的python类型

在其他世界您必须为自己创建一个代理


您可以查看此文档作为示例:

是的,但这样我无法避免问题,也无法解释原因!这并不能根除原因,即使是在掩盖问题的情况下。你是对的,我回答得太快了,没有理解全部问题。谢谢+1,但我从您的代码中得到的是“AttributeError:“AutoProxy[get_shared]”对象没有“get_comp”属性“为什么AutoProxy不工作?”?另请参见其他与我的问题相关的Shared()类及其在消费者中的使用是关键!!!真的非常感谢!从code.activestate获取代码时,您是否以任何方式更改了代码?您能否将检索类的相关代码发布到一个进程中,然后调用addChild()方法?组合的代码是绝对不变的。我将用一些相关的代码进行更新……您是否只需要2个子进程?当我运行你的代码时,它会继续启动越来越多的进程,直到失败。这是一个压缩的代码。只有两个子过程,因为它们对问题至关重要。我看到过这个进程的递归启动吗?我在Process Explorer()中看到过,但如果您运行的是Windows,您也应该在Task Manager中看到。很快就会遇到类型/引用未正确序列化的问题,是的!,调试它们很困难。它似乎不像您的示例中那样是一个循环引用,或者至少不是那么明显+1关于我问题的兴趣:-)