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

关于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秒),子进程的输出信息不再显示,后台具体发生了什么?

这是因为父进程退出速度远快于子进程,导致子进程变成了孤儿进程,同时失去了和原终端的关联,输出缓冲区被终端回收,所以你看不到子进程的打印内容,但子进程本身还在后台正常运行。

具体流程拆解:

  1. 父进程快速创建完5个子进程后,立刻执行最后的print('Main process exiting.')并退出
  2. 此时子进程因为sleep(1)还在休眠,根本没来得及执行print输出
  3. 父进程退出后,原终端会话会回收资源,子进程的标准输出/标准错误不再绑定到这个终端,后续的打印内容没有输出渠道
  4. 子进程会在休眠结束后正常执行完counter的循环,最后调用os._exit(0)退出,只是输出无法被你看到而已

如果想验证这个结论,可以让父进程等待所有子进程结束后再退出,比如在循环结束后添加一段等待逻辑:

# 在print('Main process exiting.')之前添加
for _ in range(5):
    os.waitpid(-1, 0)

这样父进程会一直等所有子进程执行完毕才退出,子进程的输出就能正常显示在终端里了。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:23:32