os.fork和multiprocessing.Process之间的行为差​​异

时间:2014-06-04 15:46:32

标签: python process multiprocessing fork python-multiprocessing

我有这段代码:

import os

pid = os.fork()

if pid == 0:
    os.environ['HOME'] = "rep1"
    external_function()
else:
    os.environ['HOME'] = "rep2"
    external_function()

和这段代码:

from multiprocessing import Process, Pipe

def f(conn):
    os.environ['HOME'] = "rep1"
    external_function()
    conn.send(some_data)
    conn.close()

if __name__ == '__main__':
    os.environ['HOME'] = "rep2"
    external_function()
    parent_conn, child_conn = Pipe()
    p = Process(target=f, args=(child_conn,))
    p.start()
    print parent_conn.recv()
    p.join()

external_function通过在环境变量HOME中找到的目录中创建必要的子目录来初始化外部程序。此功能仅在每个过程中执行一次。

使用第一个使用os.fork()的示例,按预期创建目录。但是使用multiprocessing的第二个示例,只会创建rep2中的目录。

为什么第二个示例不是在rep1rep2中创建目录?

2 个答案:

答案 0 :(得分:5)

您正在寻找的答案详细解决here。还有一个不同操作系统差异的解释。

重大问题是Windows上不存在fork系统调用。因此,在运行Windows操作系统时,您无法使用此方法。 multiprocessing是执行当前正在运行的程序的一部分的更高级别接口。因此,它 - 像分叉一样 - 创建过程当前状态的副本。所以说,它会照顾你的程序分叉。

因此,如果可用,您可以考虑将fork()作为分层程序的低级接口,并将多进程库作为分叉的更高级别接口。

希望这有帮助。

答案 1 :(得分:3)

要直接回答您的问题,external_process必定会产生一些副作用,以便在代码串行运行时,您获得的结果与同时运行它们的结果不同。这是由于您设置代码的方式,以及支持os.fork的系统中multiprocessing.Processos.fork之间缺乏差异。


os.forkmultiprocessing.Process之间唯一真正的区别是可移植性和库开销,因为Windows中不支持os.fork,并且包含multiprocessing框架multiprocessing.Process工作。这是因为os.fork调用了multiprocessing.Process,因为this answer进行了备份。

然后,重要的区别是os.fork使用Unix的分支复制当前进程中的所有内容,这意味着在分叉时两个进程与PID差异相同。在Window中,通过重新运行if __name__ == '__main__':之前的所有设置代码来模拟,这与使用subprocess库创建子流程大致相同。

对于你来说,你提供的代码片段在上面做了相当不同的事情,因为你在第二个代码片段中打开新进程之前在main中调用external_function,使得两个进程在串行但是在不同的情况下运行流程。管道也是不必要的,因为它不会模拟第一个代码的功能。

在Unix中,代码片段:

import os

pid = os.fork()

if pid == 0:
    os.environ['HOME'] = "rep1"
    external_function()
else:
    os.environ['HOME'] = "rep2"
    external_function()

import os
from multiprocessing import Process

def f():
    os.environ['HOME'] = "rep1"
    external_function()

if __name__ == '__main__':
    p = Process(target=f)
    p.start()
    os.environ['HOME'] = "rep2"
    external_function()
    p.join()

应该做同样的事情,但是从包含的多处理库中获得一些额外的开销。


如果没有进一步的信息,我们无法弄清问题是什么。如果您能提供演示此问题的代码,那将有助于我们为您提供帮助。