多くの調査とテストを行った結果、「マネージャー」は複雑でないオブジェクト レベルでこのジョブを実行することがわかりました。
以下のコードは、オブジェクトinst
がプロセス間で共有されていることを示しています。これは、子プロセスがオブジェクトを変更すると、オブジェクトのプロパティvar
がinst
外部で変更されることを意味します。
from multiprocessing import Process, Manager
from multiprocessing.managers import BaseManager
class SimpleClass(object):
def __init__(self):
self.var = 0
def set(self, value):
self.var = value
def get(self):
return self.var
def change_obj_value(obj):
obj.set(100)
if __name__ == '__main__':
BaseManager.register('SimpleClass', SimpleClass)
manager = BaseManager()
manager.start()
inst = manager.SimpleClass()
p = Process(target=change_obj_value, args=[inst])
p.start()
p.join()
print inst # <__main__.SimpleClass object at 0x10cf82350>
print inst.get() # 100
単純なオブジェクトを共有するだけであれば、上記のコードで十分です。
コンプレックスがないのはなぜ?オブジェクトがネストされていると失敗する可能性があるため(オブジェクト内のオブジェクト):
from multiprocessing import Process, Manager
from multiprocessing.managers import BaseManager
class GetSetter(object):
def __init__(self):
self.var = None
def set(self, value):
self.var = value
def get(self):
return self.var
class ChildClass(GetSetter):
pass
class ParentClass(GetSetter):
def __init__(self):
self.child = ChildClass()
GetSetter.__init__(self)
def getChild(self):
return self.child
def change_obj_value(obj):
obj.set(100)
obj.getChild().set(100)
if __name__ == '__main__':
BaseManager.register('ParentClass', ParentClass)
manager = BaseManager()
manager.start()
inst2 = manager.ParentClass()
p2 = Process(target=change_obj_value, args=[inst2])
p2.start()
p2.join()
print inst2 # <__main__.ParentClass object at 0x10cf82350>
print inst2.getChild() # <__main__.ChildClass object at 0x10cf6dc50>
print inst2.get() # 100
#good!
print inst2.getChild().get() # None
#bad! you need to register child class too but there's almost no way to do it
#even if you did register child class, you may get PicklingError :)
この動作の主な理由は、Manager
パイプ/キューなどの低レベルの通信ツールの上に構築されたキャンディーバーにすぎないためだと思います。
そのため、このアプローチはマルチプロセッシングの場合にはあまりお勧めできません。lock/semaphore/pipe/queueのような低レベルのツールや、 Redis キューやRedis のパブリッシュ/サブスクライブのような高レベルのツールを複雑なユース ケースに使用できる場合は、常に優れています(私の推奨事項のみ 笑)。