Sau nhiều nghiên cứu và thử nghiệm, tôi thấy "Người quản lý" thực hiện công việc này ở mức đối tượng không phức tạp.
Mã dưới đây cho thấy đối tượng inst
được chia sẻ giữa các quá trình, có nghĩa là thuộc tính var
của inst
được thay đổi bên ngoài khi quá trình con thay đổi.
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
Okay, mã trên là đủ nếu bạn chỉ cần chia sẻ đối tượng đơn giản.
Tại sao không phức tạp? Bởi vì nó có thể thất bại nếu đối tượng của bạn được lồng (object bên trong đối tượng):
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 :)
Tôi nghĩ lý do chính về hành vi này là bởi vì Manager
chỉ là một thanh kẹo xây dựng trên đầu trang của các công cụ giao tiếp ở mức độ thấp như ống /xếp hàng.
Vì vậy, cách tiếp cận này là không phải là cũng được đề xuất cho trường hợp đa xử lý. Sẽ tốt hơn nếu bạn có thể sử dụng các công cụ cấp thấp như khóa/semaphore/pipe/queue hoặc các công cụ cấp cao như Hàng đợi Redis hoặc Redis publish/subscribe cho trường hợp sử dụng phức tạp (chỉ giới thiệu của tôi).
liên quan: http://stackoverflow.com/questions/659865/python-multiprocessing-sharing-a-large-read-only-object-between-processes – tokland