【发布时间】:2019-01-10 20:48:12
【问题描述】:
有些文章告诉我,创建一个新的子进程,操作系统几乎会从partent复制所有数据,包括进程的struct、stack、heap等。所以,我认为全局变量,静态变量可以复制到子进程,其内容等于调用fork()时父级的值。但是以下 python 代码的结果让我感到困惑:
from multiprocessing import Process
ids = []
ids.extend([1, 2, 3, 4])
def worker(sub_id):
global ids
print("sub_id=%s, the content of ids: [%s]" % (sub_id, ",".join(["%s" % x for x in ids])))
def init():
global ids
ids.append(-100)
def main():
init()
sub_process = list()
for i in range(2):
process = Process(target=worker, args=(i, ))
process.start()
sub_process.append(process)
for p in sub_process:
p.join()
global ids
ids.append(100)
print("the main process, the content of ids: [%s]" % (",".join(["%s" % x for x in ids])))
if __name__ == "__main__":
main()
以上代码的执行结果:
sub_id=0, the content of ids: [1,2,3,4]
sub_id=1, the content of ids: [1,2,3,4]
the main process, the content of ids: [1,2,3,4,-100,100]
我预期的结果:
sub_id=0, the content of ids: [1,2,3,4, -100]
sub_id=1, the content of ids: [1,2,3,4, -100]
the main process, the content of ids: [1,2,3,4,-100,100]
不知道为什么ids函数init()的变化没有复制到子进程,但是全局部分ids.extend([1, 2, 3, 4])的变化对子进程是可见的。
感谢您的每一个回复。
【问题讨论】:
-
你在哪个平台上?什么 Python 版本?
-
我怀疑你是在Windows上,没有
fork,所以默认的启动方式是"spawn"。它的作用是启动一个全新的 Python 解释器并导入您的模块——这意味着像ids = []和ids.extend(…)这样的顶级代码将在子进程中运行(但受__main__保护的代码不会运行),所以你最终得到一个相等的列表,但它实际上并不是从父级复制的,它只是以相同的方式创建的。 -
@abarnert 非常感谢您给我如此明确的答复。是的,我在 Windows 7 和 python3.7 上运行它。正如你所说,在 windows 上没有
fork。所以,我在 centos6.5 上得到了预期的结果。
标签: python python-multiprocessing