multiprocessing.Process(使用spawn方法):继承了哪些对象? [英] multiprocessing.Process (with spawn method): which objects are inherited?
问题描述
文档(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屋!