在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
在生成模式下,子进程将仅继承运行进程对象run()方法所需的那些资源。特别是,父进程中不必要的文件描述符和句柄将不会被继承。在fork模式下(Unix的默认设置),父进程的所有资源均由子进程继承。
要回答第二个问题:不建议在macOS上使用fork(如上所述),因此,如果两个平台上的行为必须完全相同,请坚持使用。