multiprocessing.Process(使用spawn方法):继承了哪些对象? [英] multiprocessing.Process (with spawn method): which objects are inherited?

查看:1420
本文介绍了multiprocessing.Process(使用spawn方法):继承了哪些对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

文档(python 3.4)解释说,使用spawn,子进程将仅继承运行进程对象的run()方法所需的那些资源".

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

但是哪些对象是必需的"?我阅读它的方式告诉我,从run()内部可以访问的所有对象都是必需的",包括作为args传递给Process.__init__的参数,以及存储在全局变量和类中的所有对象,在全局范围内定义的函数及其属性.但是,这是不正确的.以下代码确认未继承全局变量中存储的对象:

But which objects are "necessary"? The way I read it suggested to me that all the objects that can be reached from inside run() are "necessary", including arguments passed as args to Process.__init__, plus whatever is stored in global variables, as well as classes, functions defined in global scope and their attributes. However, this is incorrect; the following code confirms that the objects stored in global variables aren't 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(A.y) # 0

def g(x, A):
    print(x) # 1
    print(A.y) # 0; really, not even args are inherited?

def main():
    global x
    x = 1
    A.y = 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 that states which objects are inherited?

确认:在Ubuntu上运行此命令会产生相同的输出. (感谢@mata澄清我忘记在main()中添加global x.此遗漏使我的示例感到困惑;如果在Ubuntu下将'spawn'切换为'fork',也会影响结果.我现在添加了global x到上面的代码.)

To confirm: running this on Ubuntu produces the same output. (Thanks to @mata for clarifying that I forgot add global x to main(). This omission made my example confusing; it would also affect the result if I were to switch 'spawn' to 'fork' under Ubuntu. I now added global x to the code above.)

推荐答案

这与将类发送到派生的Process时的腌制方式有关.一个类的腌制版本实际上并不包含其内部状态,而仅包含模块和类的名称:

This has to do with the way classes are pickled when being sent to the spawned Process. The pickled version of a class doesn't really contain its internal state, but only the module and the name of the class:

class A:
   y = 0

pickle.dumps(A)
# b'\x80\x03c__main__\nA\nq\x00.'

这里没有有关y的信息,它类似于对该类的引用.

There is no information about y here, it's comparable to a reference to the class.

当作为argumeht传递给g时,该类将在生成的过程中被取消处理,该类将在必要时导入其模块(此处为__main__)并返回对该类的引用,因此在main函数不会影响它,因为if __name__ == "__main__"块不会在子进程中执行. f直接在其模块中使用该类,因此效果基本相同.

The class will be unpickled in the spawned process when passed as argumeht to g, which will import its module (here __main__) if neccessary and return a reference to the class, therefore changes made to it in your main function won't affect it as the if __name__ == "__main__" block won't be executed in the subprocess. f directly uses the class in its module, so the effect is basically the same.

x显示不同值的原因略有不同.您的f函数将从模块中打印 global 变量x.在main()函数中,您还有另一个 local 变量x,因此在此处设置x = 1不会影响这两个进程中的模块级别x.它作为参数传递给g,因此在这种情况下,它将保留局部值为1.

The reason why x shows different values is a little different. Your f function will print the global variable x from the module. In your main() function you have another local variable x, so setting x = 1 here won't affect the module level x in neither processes. It's passed to g as argument, so in this case it will alays have the local value of 1.

这篇关于multiprocessing.Process(使用spawn方法):继承了哪些对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆