I am writing a big program as a personal project, and in it i have nested objects. For example World contains multiple environments with each enviroment containing multiple people. What i am trying to do is that i am trying to return the traits of those people from the People class to the Enviroment class to the World class and then to the main program to display said results. I am using multiprocessing to run each People object where traits actively change in it.
The code attached is a smaller version of the problem. Type1 makes a Type2 where Type2 changes its values and then Type1 values are changed based on the Type2 changes but Type1 instance doesn't detect the changes in Type2. I tried using locks, manager, values, queues and syncmanagers (all from multiprocessing) and none seemed to work.Is there something obvious i am missing? or is there a different preferred program structure to achieve what i want to do?
My expected output was for Type1 change it's specific data type values to Type2 according to the change() function in both Type1 and Type2
import multiprocessing
import time
class Type1:
def __init__(self) -> None:
self.array =[]
self.dict = {}
self.text = ""
self.number = 0
self.process_dict = {}
self.type2_dict = {}
self.num = 0
def start(self):
new_type = Type2()
p = multiprocessing.Process(target=new_type.change)
self.process_dict[f"type2{self.num}"] = p
self.type2_dict[f"type2{self.num}"] = new_type
self.num += 1
p.start()
def stop(self):
while len(self.process_dict) > 0:
_, process = self.process_dict.popitem()
process.terminate()
process.join()
def change(self):
self.array, self.dict, self.text, self.number = self.type2_dict[f"type2{self.num-1}"].get_data()
def print(self):
print(self.array)
print(self.dict)
print(self.text)
print(self.number)
print(self.process_dict)
class Type2:
def __init__(self) -> None:
self.array =[]
self.dict = {}
self.text = "Hello"
self.number = 0
def change(self):
while True:
self.array = [6,7,8,9,10]
self.dict = {"d":4,"e":5,"f":6}
self.text = "Goodbye"
self.number += 1
print("Type2 changed")
def get_data(self):
return self.array, self.dict, self.text, self.number
if __name__ == "__main__":
t = Type1()
t.start()
time.sleep(2)
print("\n\nType1 After Start:")
t.change()
t.print()
t.stop()
print("\n\nType1 After Finish:")
t.print()
print("Type1 stopped")
Trying to use a manager according to suggestions in the answer below and changing dict results in a none type which indicates that the shared_var is not shared properly across processes for different objects.
import multiprocessing
import time
class Type1:
def __init__(self, array, dict, text, number) -> None:
self.array = array
self.dict = dict
self.text = text
self.number = number
self.process_dict = {}
self.type2_dict = {}
self.num = 0
def start(self):
new_type = Type2(self.array, self.dict, self.text, self.number)
p = multiprocessing.Process(target=new_type.change, args=(self.dict,))
self.process_dict[f"type2{self.num}"] = p
self.type2_dict[f"type2{self.num}"] = new_type
self.num += 1
p.start()
def stop(self):
while len(self.process_dict) > 0:
_, process = self.process_dict.popitem()
process.terminate()
process.join()
def change(self):
self.array, self.dict, self.text, self.number = self.type2_dict[f"type2{self.num-1}"].get_data()
def print(self):
print(self.array.value)
print(self.dict.value)
print(self.text.value)
print(self.number.value)
print(self.process_dict)
class Type2:
def __init__(self, array, dict, text, number) -> None:
self.array = array
self.dict = dict
self.text = text
self.number = number
def change(self, shared_var):
while True:
self.array = [6,7,8,9,10]
self.text = "Goodbye"
self.number = 1
self.dict = shared_var
# increase each number in the dictionary by 1
for key in self.dict.keys():
self.dict[key] += 1
# shared_var = self.dict
# print("Type2 changed")
time.sleep(0.01)
def get_data(self):
return self.array, self.dict, self.text, self.number
if __name__ == "__main__":
manager = multiprocessing.Manager()
array = manager.list([1,2,3,4,5])
dict = manager.dict({"a":1,"b":2,"c":3})
text = manager.Value("s", "Hello")
number = manager.Value("i", 0)
t = Type1(array, dict, text, number)
t.start()
print("\n\nType1 After Start:")
t.change()
t.print()
time.sleep(2)
t.stop()
print("\n\nType1 After Finish:")
t.print()
print("Type1 stopped")
Multiprocessing processes cannot communicate directly, but with
multiprocessing.Manager()you can share several manager variables in the main thread and access them within processes as long as the main thread doesn't end, so I usedprocess2.join()in the second process to the main thread does not fall.In the example, process0 updates the manager variable adding +1 every 0.01 while process2 will only notify the console of the update every 1 second, the result of this is:
The processes do not interrupt each other and communication is made using the main thread as a bridge.