关于Python多进程fork脚本执行流程的技术疑问
Python多进程fork脚本执行逻辑疑问解答
脚本与运行结果
为了更清晰追踪fork后的进程PID情况,我给原Python多进程脚本添加了一行PID打印代码:
import os, time def counter(count): # run in new process for i in range(count): time.sleep(0.00001) # simulate real work print('[%s] => %s' % (os.getpid(), i)) for i in range(5): pid = os.fork() print("The pid is: ", pid) # 新增的PID追踪代码 if pid != 0: print('Process %d spawned' % pid) # in parent: continue else: counter(5) # else in child/new process os._exit(0) # run function and exit print('Main process exiting.')
运行后得到如下输出(注:输出中有拼写错误"Prociss"为笔误,不影响逻辑理解):
the pid is: 6 Prociss 6 spawned the pid is: 7 Prociss 7 spawned the pid is: 8 Prociss 8 spawned the pid is: 9 Prociss 9 spawned the pid is: 10 Prociss 10 spawned Main prociss exiting. the pid is: 0 the pid is: 0 the pid is: 0 the pid is: 0 [6] => 0 [8] => 0 [7] => 0 [6] => 1 the pid is: 0 [8] => 1 [6] => 2 [7] => 1 [9] => 0 [6] => 3 [8] => 2 [7] => 2 [9] => 1 [8] => 3 [6] => 4 [7] => 3 [8] => 4 [7] => 4 [9] => 2 [10] => 0 [9] => 3 [10] => 1 [9] => 4 [10] => 2 [10] => 3 [10] => 4 ...Program finished with exit code 0
技术疑问解答
1)counter函数的调用触发逻辑是什么?是否是新进程检测到自身pid为0时才调用counter函数?
没错,完全是这样的。这里得先搞懂os.fork()的核心返回规则:
- 在父进程中调用
os.fork(),会返回新创建的子进程的PID(一个大于0的整数) - 在刚生成的子进程中调用
os.fork(),会返回0
你的代码逻辑里,if pid !=0分支是父进程专属:它只打印子进程创建提示,然后继续循环生成下一个子进程;而else分支就是子进程的执行逻辑——子进程检测到pid为0时,会立刻调用counter(5)执行任务,完成后调用os._exit(0)直接退出(避免触发Python的默认清理流程,和父进程彻底切割)。
输出里的the pid is: 0,就是每个子进程执行到print("The pid is: ", pid)时打印的,这也侧面验证了子进程确实进入了else分支执行counter。
2)若将counter函数中的sleep时长改为1秒(原时长为0.00001秒),子进程的输出信息不再显示,后台具体发生了什么?
这是因为父进程退出速度远快于子进程,导致子进程变成了孤儿进程,同时失去了和原终端的关联,输出缓冲区被终端回收,所以你看不到子进程的打印内容,但子进程本身还在后台正常运行。
具体流程拆解:
- 父进程快速创建完5个子进程后,立刻执行最后的
print('Main process exiting.')并退出 - 此时子进程因为
sleep(1)还在休眠,根本没来得及执行print输出 - 父进程退出后,原终端会话会回收资源,子进程的标准输出/标准错误不再绑定到这个终端,后续的打印内容没有输出渠道
- 子进程会在休眠结束后正常执行完
counter的循环,最后调用os._exit(0)退出,只是输出无法被你看到而已
如果想验证这个结论,可以让父进程等待所有子进程结束后再退出,比如在循环结束后添加一段等待逻辑:
# 在print('Main process exiting.')之前添加 for _ in range(5): os.waitpid(-1, 0)
这样父进程会一直等所有子进程执行完毕才退出,子进程的输出就能正常显示在终端里了。
内容的提问来源于stack exchange,提问作者Martin Duiceivic
相关产品推荐
相关产品推荐

