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

Posted

技术标签:

【中文标题】python3中的多处理在mac和linux上运行时得到不同的值【英文标题】:Multiprocessing in python3 get different values when running on mac and linux 【发布时间】:2020-09-03 20:48:46 【问题描述】:

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

例如,当 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 得到相同的结果 但是:

    为什么 mac 会采取不同的默认行为? 如何在我的项目中设置默认行为?

【问题讨论】:

【参考方案1】:

我在 macOS 10.15 和 Python 3.6.5 上看到了前一个输出(你在 Linux 上看到的那个),结果他们在 Python 3.8 中改变了这种行为(你必须运行 3.8 或更高版本):

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

在 3.8 版中更改:在 macOS 上,spawn start 方法现在是默认设置。 fork start 方法应该被认为是不安全的,因为它可能导致子进程崩溃。见bpo-33725。

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

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

【讨论】:

以上是关于python3中的多处理在mac和linux上运行时得到不同的值的主要内容,如果未能解决你的问题,请参考以下文章

Linux 上 Java 和 Zeroconf (avahi) 的多播问题

Mac OS X Mavericks 上 PyQt5、Python3 和 Anaconda3 的问题

Linux 中的 Segfault,在 Mac OS 上运行良好

Python3安装

用python3的多进程和协程处理MySQL的数据

python3.6.5 路径处理与规范化