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

使用multiprocess.Process调用exec()后,如何等待多进程执行完毕?

问题:multiprocessing.connection.wait()未等待子进程执行完毕

我需要等待多个进程执行完毕,因需在子进程执行前调整其oom_score,故使用multiprocess.Process。尝试通过multiprocessing.connection.wait结合进程的sentinel值实现等待,但代码输出的两个时间戳仅差数毫秒,wait()并未等待命令执行完毕。而pp.join()可正常生效,且子进程非守护进程,Python会等待其完成。

参考代码:

import multiprocessing
import multiprocessing.connection
import os
from datetime import datetime

def adj_oom_score_exec(*command: str):
    with open("/proc/{}/oom_score_adj".format(os.getpid()), "w") as f:
        f.write("500")
    os.execv(command[0], command)
    exit(198)

pp = multiprocessing.Process(target=adj_oom_score_exec, args=["/usr/bin/sleep", "1"])
pp.start()
print(datetime.now())
multiprocessing.connection.wait([pp.sentinel])
print(datetime.now())

原因分析

multiprocessing.Process的sentinel是关联原Python子进程的文件描述符。当子进程调用os.execv后,原Python进程会被新的进程(比如示例中的sleep)替换,原Python进程的资源被立即释放,导致sentinel对应的管道触发可读状态,multiprocessing.connection.wait()因此提前返回,但此时execv启动的新进程仍在运行。

而pp.join()生效的原因是:join()等待的是进程对象对应的PID终止,execv不会改变进程PID,因此join()会一直等到execv启动的进程结束。


解决方案

方案1:用subprocess替代execv,让原Python子进程等待命令完成

修改子进程函数,使用subprocess.run()启动命令并等待其执行完毕,这样原Python子进程会在命令结束后才退出,sentinel的wait()就能正确等待整个流程完成:

import multiprocessing
import multiprocessing.connection
import os
from datetime import datetime
import subprocess

def adj_oom_score_exec(*command: str):
    with open(f"/proc/{os.getpid()}/oom_score_adj", "w") as f:
        f.write("500")
    # 等待命令执行完毕后,子进程才会退出
    subprocess.run(command)

pp = multiprocessing.Process(target=adj_oom_score_exec, args=["/usr/bin/sleep", "1"])
pp.start()
print(datetime.now())
multiprocessing.connection.wait([pp.sentinel])
print(datetime.now())

方案2:直接使用Process.join()等待多进程

如果不需要用multiprocessing.connection.wait(),直接遍历所有进程调用join()即可,这也是最直接的方式:

import multiprocessing
import os
from datetime import datetime
import subprocess

def adj_oom_score_exec(*command: str):
    with open(f"/proc/{os.getpid()}/oom_score_adj", "w") as f:
        f.write("500")
    subprocess.run(command)

# 创建多个进程
processes = [
    multiprocessing.Process(target=adj_oom_score_exec, args=["/usr/bin/sleep", "1"]),
    multiprocessing.Process(target=adj_oom_score_exec, args=["/usr/bin/sleep", "2"])
]

# 启动所有进程
for p in processes:
    p.start()

print(datetime.now())

# 等待所有进程完成
for p in processes:
    p.join()

print(datetime.now())

方案3:手动跟踪execv后的进程PID(不推荐)

如果坚持使用os.execv,可以在子进程中记录当前PID(即execv后的进程PID),然后在主进程中用os.waitpid()等待该PID。但这种方式需要进程间传递PID,复杂度较高,不如前两种方案简洁。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 01:47:44