multiprocessing.Process(使用spawn方法):继承哪些对象?

max*_*max 8 python multiprocessing python-3.x python-multiprocessing

docs(python 3.4)解释说spawn,"子进程只会继承运行进程对象run()方法所需的那些资源".

但哪些对象是"必要的"?我读它的方式告诉我,从内部可以到达的所有对象run()都是"必要的",包括传递args给的参数Process.__init__,加上存储在全局变量中的任何东西,以及在全局范围内定义的类,函数及其属性.但是,这是不正确的; 以下代码确认不会继承存储在全局变量中的对象:

# 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()
Run Code Online (Sandbox Code Playgroud)

是否有明确的规则说明哪些对象是继承的?

编辑:

要确认:在Ubuntu上运行它会产生相同的输出.(感谢@mata澄清,我忘添加global xmain()这种省略使我示例混淆;它也将影响结果,如果我是切换'spawn''fork'在Ubuntu下我现在加入global x到上面的代码).

mat*_*ata 5

这与发送到生成的进程时类被pickle的方式有关.类的pickle版本并不真正包含其内部状态,而只包含模块和类的名称:

class A:
   y = 0

pickle.dumps(A)
# b'\x80\x03c__main__\nA\nq\x00.'
Run Code Online (Sandbox Code Playgroud)

这里没有关于y它的信息,它与类的引用相当.

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

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