pythonmultithreadingmultiprocessing

Changes in child processes variables not reflected in parent object


I have a parent class in Python that can start a process in a child class. The child class has a multiprocessing.Process that changes some variables. I would expect changes to be visible for the parent class since the object is created there, but somehow, the variables are not shared. The process is started as a fork.

Here is an example code:

import multiprocessing
from multiprocessing import Queue, Process
import time

class Parent:
    def __init__(self):
        print(multiprocessing.get_start_method())
        self.child = Child()

    def start(self):
        self.child.start_child()

    def print_child_variable(self):
        print('Parent: Child Variable: ' + str(self.child.some_variable))


class Child:

    def __init__(self):
        self.some_variable = None
        self.status = False

    def start_child(self):
        self.status = True

        do_something_process = Process(target=self.do_something)
        do_something_process.start()
    

    def do_something(self):
        self.some_variable = True
        print('Child: some variable after changing: ' + str(self.some_variable))

    def print_some_variable(self):
        print('Child: some variable: ' + str(self.some_variable))
    

if __name__ == '__main__':
    parent = Parent()
    parent.print_child_variable()
    time.sleep(1)
    parent.start()
    parent.print_child_variable()
    time.sleep(1)
    parent.print_child_variable()
    time.sleep(1)
    parent.child.print_some_variable()

The output:

fork
Parent: Child Variable None
Parent: Child Variable None
Child: some variable after chaging True
Parent: Child Variable None
Child: some variable None

I would expect that after the change, the variable some_variable will be true even if checked from the parent object. Can anyone help me understand what is going on?


Solution

  • Here is how I would create an attribute that can represent boolean values and be sharable across multiple processes. See multiprocessing.Value.

    from multiprocessing import Process, get_start_method, Value
    import ctypes
    import time
    
    class Parent:
        def __init__(self):
            print(get_start_method())
            self.child = Child()
    
        def start(self):
            self.child.start_child()
    
        def print_child_variable(self):
            print('Parent: Child Variable:', self.child.some_variable.value)
    
    
    class Child:
        def __init__(self):
            # This Value instance can only have values True and False:
            self.some_variable = Value(ctypes.c_bool, False)
    
        def start_child(self):
            do_something_process = Process(target=self.do_something)
            do_something_process.start()
    
    
        def do_something(self):
            self.some_variable.value = True
            print('Child: some variable after changing:', self.some_variable.value)
    
        def print_some_variable(self):
            print('Child: some variable:', self.some_variable.value)
    
    
    if __name__ == '__main__':
        parent = Parent()
        parent.print_child_variable()
        time.sleep(1)
        parent.start()
        parent.print_child_variable()
        time.sleep(1)
        parent.print_child_variable()
        time.sleep(1)
        parent.child.print_some_variable()
    

    Prints:

    fork
    Parent: Child Variable: False
    Parent: Child Variable: False
    Child: some variable after changing: True
    Parent: Child Variable: True
    Child: some variable: True