我拼命试图在进程之间共享一些不可拾取的对象。 我使用了 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()
因此,我如何共享一个不可拾取的对象?
我希望我足够清楚和明确, 并感谢您的宝贵时间。