python3 中的多处理在 mac 和 linux 上的 运行 时获得不同的值

Multiprocessing in python3 get different values when running on mac and linux

Python 中的多处理 3 在 Mac 和 Linux 上 运行 时获得不同的值。

例如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上,我测试了macos14和macos15,结果是:

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

可能是ForkPoolWorker和SpawnPoolWorker造成的差异?

查看后发现有3种方式可以创建process:spawn、fork、forkserver。 所以我添加:

multiprocessing.set_start_method('fork')

Linux 和 Mac 得到相同的结果 但是:

  1. 为什么 mac 执行不同的默认行为?
  2. 如何在我的项目中设置默认行为?

我在 Python 3.6.5 的 macOS 10.15 上看到了以前的输出(你在 Linux 上看到的那个),结果他们在 Python 3.8(您必须是 运行ning 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.

spawn模式下,子进程只会继承运行进程对象运行()方法所必需的那些资源。特别是,不会从父进程继承不必要的文件描述符和句柄。在 fork 模式(Unix 的默认模式)下,父进程的所有资源都由子进程继承。

回答你的第二个问题:推荐在macOS上使用fork(如上所述),所以如果你必须在两个平台上具有完全相同的行为,坚持 spawn.