Multiprocessing.Process (with spawn method): which objects are inherited?

The docs (python 3.4) explain that with spawn , the child process will inherit only those resources that are needed to run the run() object method.

But which objects are "necessary"? The way I read this tells me that all objects that can be reached from inside run() are "necessary", including arguments passed as args to Process.__init__ , plus everything that is stored in global variables, as well as classes, functions defined globally and their attributes. However, this is not true; The following code confirms that objects stored in global variables are not inherited:

 # running under python 3.4 / Windows # but behaves the same under Unix import multiprocessing as mp x = 0 class A: y = 0 def f(): print(x) # 0 print(Ay) # 0 def g(x, A): print(x) # 1 print(Ay) # 0; really, not even args are inherited? def main(): global x x = 1 Ay = 1 p = mp.Process(target = f) p.start() q = mp.Process(target = g, args = (x, A)) q.start() if __name__=="__main__": mp.set_start_method('spawn') main() 

Is there a clear rule indicating which objects are inherited?

EDIT:

To confirm: running this on Ubuntu gives the same result. (Thanks to @mata for clarifying that I forgot to add global x to main() . This omission made my example confusing, it will also affect the result if I have to switch 'spawn' to 'fork' under Ubuntu. global x to the above code.)

+5
source share
1 answer

This is due to the way the classes are pickled when sent to the child process. The branded version of the class does not actually contain its internal state, but only the module and class name:

 class A: y = 0 pickle.dumps(A) # b'\x80\x03c__main__\nA\nq\x00.' 

There is no information about y , this is comparable to a class reference.

The class will crumble in the generated process when it will be passed as argumeht to g , which will import its module (here __main__ ), if necessary, and return a reference to the class, so changes made to it in main will not affect it, since the if __name__ == "__main__" block will not be executed in the subprocess. f directly uses the class in its module, so the effect is basically the same.

The reason x shows different values ​​is slightly different. Your f function will output the global variable x from the module. In your main() function, you have another local variable x , so setting x = 1 here will not affect the level of module x in any of the processes. It is passed to g as an argument, so in this case it will have a local value of 1.

+4
source

Source: https://habr.com/ru/post/1215882/


All Articles