thread.join()在目标函数使用subprocess.run()时失效问题解决
问题根源
逻辑失效的核心原因是你调用subprocess.run()执行带&和nohup的shell命令时,shell进程会把后台任务提交后立刻退出,根本不会等待实际运行的Python业务进程结束。这就导致你的func()在后台进程刚启动时就直接执行完毕,对应线程马上退出,th.join()完全等不到后台进程跑完,自然没法实现串行。
另外你的代码里还有两处低级错误:
- 第一段代码的
for i in range(processes)行尾漏了冒号 - 线程守护属性拼写错误,正确属性名是
daemon,不是deamon
修正方案
别靠shell的nohup和&托管后台进程,直接用subprocess.Popen启动子进程、留存每个进程的句柄,等当前批次所有子进程全部执行完成后再退出func(),外层的串行逻辑就能正常生效。
修正后的任务执行函数
import subprocess import os def func(input_value, processes): process_pool = [] # 启动对应数量的子进程,不通过shell托管 for _ in range(processes): # 注意把func_background替换成脚本的实际绝对路径,避免找不到文件 proc = subprocess.Popen( ["python3", "func_background", str(input_value)], stdout=open("nohup.out", "ab"), # 对齐原nohup的输出重定向逻辑 stderr=subprocess.STDOUT, start_new_session=True # 实现原nohup的会话隔离效果,父进程退出不影响子进程 ) process_pool.append(proc) # 阻塞等待当前批次所有进程执行完毕 for proc in process_pool: proc.wait()
外层调度逻辑
实际上你根本不需要引入多线程,func本身已经是阻塞执行的,直接循环调用就能实现不同input_value对应批次的串行执行:
list_input_values = [input_value_1, input_value_2] for input_val in list_input_values: func(input_val, 4) # 只有当前input_value对应的4个进程全部跑完,才会启动下一批次
如果你一定要保留线程写法,修正之前的拼写错误即可,逻辑同样能正常运行:
import threading list_input_values = [input_value_1, input_value_2] for input_val in list_input_values: th = threading.Thread(target=func, args=(input_val, 4)) th.daemon = True th.start() th.join()
补充提示
- 不要随便用
shell=True拼接命令,既存在命令注入风险,也会导致你拿不到实际业务进程的句柄,没法追踪进程运行状态 - 如果需要更灵活的CPU资源控制,也可以直接用
concurrent.futures.ProcessPoolExecutor限制总并发数,不用靠批次串行硬限制。
内容的提问来源于stack exchange,提问作者robertoimuno
相关产品推荐
相关产品推荐

