Après beaucoup de recherches et de tests, j'ai trouvé "Manager" faire ce travail dans un niveau d'objet non complexe.
Le code ci-dessous montre que l'objet inst
est partagé entre les processus, ce qui signifie que la propriété var
de inst
est modifiée à l'extérieur lorsque le processus fils le modifie.
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
Bon, le code ci-dessus est assez si vous avez besoin de partager des objets simples .
Pourquoi pas de complexe? Parce que il peut échouer si votre objet est imbriqué (objet à l'intérieur objet):
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 :)
Je pense que la raison principale de ce comportement est dû au fait Manager
est juste un candybar construire sur des outils de communication de bas niveau comme tuyau /queue. Par conséquent, cette approche est et non, ce qui est recommandé dans le cas du multitraitement. C'est toujours mieux si vous pouvez utiliser des outils de bas niveau comme lock/sémaphore/pipe/queue ou des outils de haut niveau comme Redis queue ou Redis publie/abonne pour un cas d'utilisation compliqué (seulement ma recommandation lol).
connexes: http://stackoverflow.com/questions/659865/python-multiprocessing-sharing-a-large-read-only-object-between-processes – tokland