在Mac和Linux上运行时,python3中的多处理获得不同的值

在Mac和Linux上运行时,python3中的多处理会获得不同的值。 与fork主进程相同,原始变量的值应克隆到子进程。 但是经过测试,Linux的结果与mac不同。 这是代码

#!/usr/bin/env python
# coding=utf-8
import multiprocessing

test_temp = "a"


def check_value_in_other_process():
    print(f"[{multiprocessing.current_process().name}] test_temp={test_temp}")


def change_value():
    global test_temp
    test_temp = "b"


if __name__ == '__main__':

    print(f"[{multiprocessing.current_process().name}] origin test_temp={test_temp}")
    change_value()
    print(f"[{multiprocessing.current_process().name}] changed test_temp={test_temp}")

    pool = multiprocessing.Pool(4)
    pool.apply_async(func=check_value_in_other_process)
    pool.close()
    pool.join()

在Linux上,我使用debian 9和CentOS 8进行了测试,结果是

[MainProcess] origin test_temp=a
[MainProcess] changed test_temp=b
[ForkPoolWorker-1] test_temp=b

在mac上,我使用mac os 14和mac os 15进行了测试,结果是:

[MainProcess] origin test_temp=a
[MainProcess] changed test_temp=b
[SpawnPoolWorker-2] test_temp=a

也许,差异是由ForkPoolWorker和SpawnPoolWorker引起的吗?

经过检查,我发现有3种创建过程的方法:spawn,fork,forkserver。 所以我添加:

multiprocessing.set_start_method('fork')

Linux和Mac获得相同的结果 但: 1,为什么Mac扮演不同的默认行为? 2,如何在项目中设置默认行为?

评论
  • 如果他
    如果他 回复

    我在带有Python 3.6.5的macOS 10.15上看到前一个输出(在Linux上看到的输出),事实证明,它们在Python 3.8(您必须运行3.8或更高版本)中更改了此行为:

    https://docs.python.org/3/library/multiprocessing.html#contexts-and-start-methods

    Changed in version 3.8: On macOS, the spawn start method is now the default. The fork start method should be considered unsafe as it can lead to crashes of the subprocess. See bpo-33725.

    在生成模式下,子进程将仅继承运行进程对象run()方法所需的那些资源。特别是,父进程中不必要的文件描述符和句柄将不会被继承。在fork模式下(Unix的默认设置),父进程的所有资源均由子进程继承。

    要回答第二个问题:不建议在macOS上使用fork(如上所述),因此,如果两个平台上的行为必须完全相同,请坚持使用。