首页 > 解决方案 > 多处理问题:函数调用

问题描述

from multiprocessing import Process

a=[]

def one():
    for i in range(3):
        a.append(i)

def main():
    p1=Process(target=one)
    p1.start()
if __name__=='__main__':
    main()

print('After calling from Multi-process')
print(a)

one()
print('Calling outside Multi-process')
print(a)

输出:

After calling from Multi-process:
[]
Calling outside Multi-process:
[0, 1, 2]

为什么从a调用函数时没有附加元素?oneProcess

标签: pythonmultiprocessingpython-multiprocessing

解决方案


我检查了文档,我有一些了解,这可能对您有所帮助。

python文档对多处理包中的Process类有如下描述:

上下文和启动方法 根据平台,多处理支持三种启动进程的方法。这些启动方法是

  • spawn 父进程启动一个新的 python 解释器进程。子进程将仅继承运行进程对象的 run() 方法所需的那些资源。特别是,不会继承父进程中不必要的文件描述符和句柄。与使用 fork 或 forkserver 相比,使用这种方法启动进程相当慢。

    在 Unix 和 Windows 上可用。Windows 和 macOS 上的默认设置。

  • fork 父进程使用 os.fork() 来 fork Python 解释器。子进程在开始时实际上与父进程相同。父进程的所有资源都由子进程继承。请注意,安全地分叉多线程进程是有问题的。

    仅在 Unix 上可用。Unix 上的默认值。

  • forkserver 当程序启动并选择forkserver启动方式时,一个服务器进程被启动。从那时起,每当需要一个新进程时,父进程都会连接到服务器并请求它派生一个新进程。fork 服务器进程是单线程的,因此使用 os.fork() 是安全的。没有不必要的资源被继承。

    在支持通过 Unix 管道传递文件描述符的 Unix 平台上可用。

从描述中我们可以知道,Process该类在几种情况下os.fork用来运行指定的方法。target

os.fork将完全复制父进程的所有对象,除了文件描述符等资源供子进程使用。

因此,子进程中运行a的方法所操作的列表one是子进程自身独有的内存空间,不会改变a父进程所拥有的列表。

为了验证,我们可以简单地修改one方法,例如:

def one():
    for i in range(3):
        a.append(i)
        print('pid:', os.getpid(), 'ppid:', os.getppid(), 'list:', a)

然后我们再次运行这个脚本,我们会得到如下结果:

After calling from Multi-process
[]                                   // Print directly in the parent process
pid: 6990 ppid: 1419 list: [0]       // Call the `one` method in the parent process
pid: 6990 ppid: 1419 list: [0, 1]    // Call the `one` method in the parent process
pid: 6990 ppid: 1419 list: [0, 1, 2] // Call the `one` method in the parent process
Calling outside Multi-process
[0, 1, 2]                            // Print directly in the parent process
pid: 6991 ppid: 6990 list: [0]       // Call the `one` method in the child process
pid: 6991 ppid: 6990 list: [0, 1]    // Call the `one` method in the child process
pid: 6991 ppid: 6990 list: [0, 1, 2] // Call the `one` method in the child process

推荐阅读