You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python多进程是否复制父进程全部模块?为何子进程可访问外部内容?

在Python多进程中子进程为何能访问目标函数外的内容?

好问题!这其实和Python多进程的启动机制以及内存复制逻辑直接相关,咱们一步步掰扯清楚:

子进程是不是复制了父进程的所有内容?

这得分操作系统来看:

  • Unix/Linux类系统:Python的multiprocessing默认用fork机制创建子进程。fork的时候会复制父进程的整个地址空间——包括所有已加载的模块、全局变量、函数定义,甚至已经打开的文件句柄等。不过别担心内存会瞬间翻倍,这里用的是写时复制(Copy-On-Write):只有当子进程或者父进程修改某个内存区域时,才会真正复制一份该区域的内容,平时只是共享内存,效率很高。
  • Windows系统:Windows没有fork,所以multiprocessing用的是spawn机制。简单说就是重新启动一个Python解释器,然后重新导入父进程的整个脚本模块,再执行指定的目标函数。这种情况下,子进程能访问的是模块级别定义的内容(比如全局函数、导入的模块),因为脚本被重新加载了一遍。

为什么子进程能访问目标函数外的导入模块和函数?

拿你提供的代码举例:

from multiprocessing import Process, Pipe
def test1(): return "hello"
def simpleChildProcess( childPipe ):
    # simpleChildProcess可以访问test1函数
    foo = test1()
    childPipe.send( foo )
parentPipe, childPipe = Pipe()
childProcess = Process( target=simpleChildProcess, args=(childPipe,) )
childProcess.start()
print "Pipe Contains: %s" % parentPipe.recv()

这里的test1是定义在模块全局作用域的函数,不管是fork还是spawn模式,子进程都能拿到它:

  • 如果是fork模式:子进程直接继承了父进程内存里已经定义好的test1函数对象,自然能调用;
  • 如果是spawn模式:子进程启动时会重新执行整个脚本(这时候建议把启动代码放在if __name__ == '__main__':块里,避免无限创建子进程的坑),所以test1的定义会被重新加载,simpleChildProcess当然能调用它。

同样的道理,你导入的multiprocessing模块也是模块级别的,子进程要么通过fork继承过来,要么在spawn时重新导入,所以也能正常使用。

顺便提个Windows下的小优化:把你的代码改成这样更规范,避免踩坑:

from multiprocessing import Process, Pipe

def test1(): return "hello"

def simpleChildProcess( childPipe ):
    foo = test1()
    childPipe.send( foo )

if __name__ == '__main__':
    parentPipe, childPipe = Pipe()
    childProcess = Process( target=simpleChildProcess, args=(childPipe,) )
    childProcess.start()
    print "Pipe Contains: %s" % parentPipe.recv()

额外注意点

  • 不是所有内容都能被继承/访问:比如父进程中打开的网络连接、一些非可序列化(picklable)的对象,在子进程中可能无法正常使用,尤其是spawn模式下,传递给子进程的参数必须是能被pickle序列化的;
  • 写时复制的局限性:如果父进程在创建子进程后修改了某个全局变量,子进程看不到这个修改(因为修改时已经复制了内存区域),反之亦然。

内容的提问来源于stack exchange,提问作者ThunderJack

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 06:52:57