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 得到相同的结果
但是:
- 为什么 mac 执行不同的默认行为?
- 如何在我的项目中设置默认行为?
我在 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.
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 得到相同的结果 但是:
- 为什么 mac 执行不同的默认行为?
- 如何在我的项目中设置默认行为?
我在 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.