ArunJose
ArunJose

Reputation: 2159

Python multiprocessing the value set in run function not reflected in the object

I am running the below code

from multiprocessing import Process
from multiprocessing import Value
class TestMultiprocess(Process):
  def __init__(self):
    super().__init__()
    self.variable={"value":"initial"}
  def run(self):
    print("executing the run function")
    self.variable={"value":"new"}
    

t=TestMultiprocess()
t.start()
t.join()
print(t.variable) #prints {"value":"initial"}, (I expected {"value":"new"})

I am setting the value of the variable in the run function but this value is not getting reflected in the object (It still holds the value initialised in constructor). Why is this??

How do I set/change am attribute value in the run function of the class inheriting multiprocessing and use the value from the client code which creates the object of the class. I looked at multiprocessing.values but this does not have support for dictionaries. The attribute value I need to set is a dictionary

Upvotes: 1

Views: 100

Answers (1)

Booboo
Booboo

Reputation: 44108

Your process is running in a different address space. Therefore, your TestMultiProcess instance must be serialized and sent to that child process's address space where it is then deserialized (all of this is done with the pickle module). So what is being updated is a copy of your instance that is in the child process's address space; the main process's instance is never updated.

The simplest solution is to used a managed dictionary. The actual dictionary "lives" in the address space of the Manager and variable managed_dict in the code below is actually a proxy object such that when one of its methods is called, the method name and its arguments are sent to the Manager process where the actual dictionary is updated:

from multiprocessing import Process, Manager

class TestMultiprocess(Process):
    def __init__(self, managed_dict):
        super().__init__()
        self.managed_dict = managed_dict
        self.managed_dict["value"] = "initial"

    def run(self):
        print("executing the run function")
        self.managed_dict["value"] = "new"


# Required for Windows:
if __name__ == '__main__':
    with Manager() as manager:
        managed_dict = manager.dict()
        t = TestMultiprocess(managed_dict)
        print(t.managed_dict)
        t.start()
        t.join()
        print(t.managed_dict)

Prints:

{'value': 'initial'}
executing the run function
{'value': 'new'}

Upvotes: 2

Related Questions