import random
import os
from multiprocessing import Process
num = random.randint(0, 100)
def show_num():
print("pid:{}, num is {}".format(os.getpid(), num))
if __name__ == '__main__':
print("pid:{}, num is {}".format(os.getpid(), num))
p = Process(target=show_num)
p.start()
p.join()
print('Parent Process Stop')
上面的代码显示了创建流程的基本用法。如果我在Windows环境中运行此脚本,则变量num在父进程和子进程中是不同的。但是,当脚本在Linux环境之间运行时,变量num相同。 我了解他们的创建过程机制是不同的。例如,Windows系统没有fork方法。 但是,有人可以给我更详细的解释他们之间的区别吗? 非常感谢你。
答案 0 :(得分:0)
与您在文章中描述的行为不同的是您所提到的:start method用于创建流程。在Unix风格的操作系统上,默认值为fork
。在Windows上,唯一可用的选项是spawn
。
叉子
如this Wiki page的“概述”部分所述(顺序略有不同):
fork操作为子代创建一个单独的地址空间。的 子进程拥有 父进程。
子进程调用exec系统调用,将自身与 其他程序:停止执行其先前的程序,以支持 另一个。
这意味着,在使用fork时,子进程在其地址空间中已经具有变量num
并在使用它。再次不调用random.randint(0, 100)
。
生成
正如多处理文档所述:
父进程开始一个全新的python解释器进程。
在这个新的解释器过程中,将生成从其派生儿童的模块。过于简单,这是第二次python.exe your_script.py
。因此,通过向子进程分配对num
的另一个调用的返回值,在子进程中创建了一个新变量random.randint(0, 100)
。因此,num
的内容很可能在两个进程之间有所不同。
顺便说一句,这也是您绝对需要保护实例化和存储的原因。使用if __name__ == '__main__'
作为启动方法时,以spawn
习惯用法开始一个过程,否则结果如下:
RuntimeError:
An attempt has been made to start a new process before the
current process has finished its bootstrapping phase.
This probably means that you are not using fork to start your
child processes and you have forgotten to use the proper idiom
in the main module:
if __name__ == '__main__':
freeze_support()
...
The "freeze_support()" line can be omitted if the program
is not going to be frozen to produce an executable.
您也可以在POSIX操作系统中使用spawn
来模仿您在Windows上看到的行为:
import random
import os
from multiprocessing import Process, set_start_method
import platform
num = random.randint(0, 100)
def show_num():
print("pid:{}, num is {}".format(os.getpid(), num))
if __name__ == '__main__':
print(platform.system())
# change the start method for new processes to spawn
set_start_method("spawn")
print("pid:{}, num is {}".format(os.getpid(), num))
p = Process(target=show_num)
p.start()
p.join()
print('Parent Process Stop')
输出:
Linux
pid:26835, num is 41
pid:26839, num is 13
Parent Process Stop