Python BaseManager和无法拾取的对象

时间:2018-06-28 08:54:28

标签: python multiprocessing

我拼命试图在进程之间共享一些不可拾取的对象。 我使用了 concurrent.futures.ProcessPoolExecutor ,并且有问题的对象是由python模块 ifcopenshell 提供的,所以我无法手动对其进行拾取。

当我尝试将这样的对象作为参数传递给流程作业时,出现此错误:

Traceback (most recent call last):
  File "./test.py", line 105, in <module>
    main()
  File "./test.py", line 85, in main
    stats.set_elements('wall', w)
  File "<string>", line 2, in set_elements
  File "/usr/lib/python3.6/multiprocessing/managers.py", line 756, in _callmethod
    conn.send((self._id, methodname, args, kwds))
  File "/usr/lib/python3.6/multiprocessing/connection.py", line 206, in send
    self._send_bytes(_ForkingPickler.dumps(obj))
  File "/usr/lib/python3.6/multiprocessing/reduction.py", line 51, in dumps
    cls(buf, protocol).dump(obj)
TypeError: can't pickle SwigPyObject objects

我尝试使用pathos和dill,但它们也无法处理,因此我转向了BaseManager选项。 因此,现在,我需要共享一个此类对象的字典,并将其存储在以下(简化的)类中:

class Stats(object):
    def __init__(self):

        self.elements = dict()

    def set_elements(self, d):
        self.elements = d

此字典应通过多个并行进程进行更新。 为此,我读到我可以如下使用BaseManager:

class StatsManager(BaseManager):
    pass

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

    def set_elements(self, *args):
        callmethod = object.__getattribute__(self, '_callmethod')
        return callmethod(self.set_elements.__name__, (*args,))

StatsManager.register("Stats", Stats, StatsProxy)

(这里使用代理并不是有趣的部分,因为对象将被添加到字典中,因此没有并发问题,但是我还有其他需要同步的属性,因此我要像这样处理它们)

然后实例化并使用Stats实例,例如:

m = StatsManager() # doesn't work if I specify an address and an authkey either
m.start()
stats = m.Stats()

filename = "tests/test_wall_simple.ifc"
f = ifc.open(filename)
w = f.by_type('IfcWall')[0]
stats.set_elements({'wall', w}) # this fails 

我也尝试过:

stats = Stats()

def getStats():
    global stats
    return stats

class SManager(BaseManager):
    pass
SManager.register('getStats', callable=getStats)

m = SManager(address=('127.0.0.1', 5000), authkey=b'abc')
m.start()
stats = m.getStats()

依此类推,无论是否使用

m.connect()

因此,我如何共享一个不可拾取的对象?

我希望我足够清楚和明确, 并感谢您的宝贵时间。

0 个答案:

没有答案