You just need to create "proxyable", managed objects just like the ones returned by the SyncManager
instance that is created when you call multiprocessing.Manager()
, for example managed dict
instances:
from multiprocessing import Pool
from multiprocessing.managers import BaseManager, NamespaceProxy
from multiprocessing.pool import Pool
class MyObject(object):
def __init__(self):
self.level=1
def process(self):
self.level=2
# and other many things that modify the object...
def delegatee(self):
return self
# Must explicitly create a customized proxy if attributes in addition to methods will be accessed
# And that forces us to name each method, e.g. process:
class MyObjectProxy(NamespaceProxy):
_exposed_ = ('__getattribute__', '__getattr__', '__setattr__', 'process', 'delegatee')
def process(self):
callmethod = NamespaceProxy.__getattribute__(self, '_callmethod')
return callmethod('process')
def delegatee(self):
callmethod = NamespaceProxy.__getattribute__(self, '_callmethod')
return callmethod('delegatee')
"""
or you can just use the following generic signature for each of your methods:
def process(self, *args, **kwds):
callmethod = NamespaceProxy.__getattribute__(self, '_callmethod')
return callmethod('process', args, kwds)
"""
class MyObjectManager(BaseManager):
pass
if __name__ == "__main__":
MyObjectManager.register('MyObject', MyObject, MyObjectProxy)
with MyObjectManager() as manager:
objects = [manager.MyObject() for i in range(10)]
pool = Pool(3)
async_results = []
for o in objects:
async_results.append(pool.apply_async(o.process, [], {}))
# or just:
#async_results.append(pool.apply_async(o.process))
pool.close()
for r in async_results:
r.get()
for o in objects:
print(o.level)
obj0 = objects[0]
print(type(obj0))
delegatee = obj0.delegatee()
print(type(delegatee))
print('delegatee level =', delegatee.level)
Prints:
2
2
2
2
2
2
2
2
2
2
<class '__main__.MyObjectProxy'>
<class '__main__.MyObject'>
delegatee level = 2
But note that each method invocation or attribute access is via a proxy and is more or less equivalent to a remote procedure call.