【问题标题】:Python MultiProcessing apply_async wait for all processes to finishPython MultiProcessing apply_async 等待所有进程完成
【发布时间】:2018-12-03 21:51:33
【问题描述】:

我一直在尝试并行管理一系列批处理文件进程,同时存在相关的子进程组。我希望得到的是能够并行运行 group1 的所有进程,然后在运行 group2 之前等待所有进程完成,依此类推。想象一下一系列进程组,其中每个进程都是一个单独的现有批处理文件(batch_i.bat)

根据我对多进程模块的理解,我有以下代码,所以我希望在调用最终打印命令时,所有日志文件都是完整的,可以打印所有数字。但是,我注意到 python 代码成功完成而没有完成批处理。

Python 代码:

import multiprocessing as mp
import subprocess

def worker(cmdlist, log):
    with open(log, 'w') as logfile:
        p = subprocess.Popen(cmdlist, stderr=logfile, stdout=logfile)
    # return p.returncode

# --------------------------------------------
# Main Process (Group 1)
# --------------------------------------------
if __name__ == '__main__':
    group1 = [batch_1 , batch_2 , batch_3 , ..., batch_10]
    group2 = [batch_11, batch_12, batch_13, ..., batch_20]
    group3 = [batch_21, batch_22, batch_23, ..., batch_30]

    # Multi-Core Exec
    all_process = group1 
    all_results = []
    pool = mp.Pool(processes=4)

    for myProcess in all_process:
        print("Starting Process: %s" %myProcess)
        log = os.path.splitext(myProcess)[0] + ".log"
        res = pool.apply_async(worker, args=[myProcess, log])
        all_results.append(res)

    pool.close()
    pool.join()
    print("All sub-processes completed")

    for res in all_results:
        res.get()
    print("All sub-processes completed: %s" % [res.successful() for res in all_results])

# --------------------------------------------
# call group 2 and wait for completion
# --------------------------------------------
....

# --------------------------------------------
# call group 3 and wait for completion
# --------------------------------------------
...

其余代码调用 group2 中依赖于 group 1 完成的所有进程,依此类推


批处理文件:batch_i.bat:

在这种情况下,批处理文件是一个示例,除了打印出很多数字外什么都不做,我重复了几次循环以确保批处理文件需要足够长的时间才能完成。

@echo off
echo Start of Loop

for /L %%n in (1,1,40000) do echo %%n
for /L %%n in (1,1,40000) do echo %%n
for /L %%n in (1,1,40000) do echo %%n
for /L %%n in (1,1,40000) do echo %%n

echo End of Loop

输出如下:

> *** Running Base Cases: ***
>      on 4 CPUs Process: C:\Users\mamo8001\Project\Clustering\01 Codes\testNum.bat Process: C:\Users\mamo8001\Project\Clustering\01
> Codes\testNum2.bat Process: C:\Users\mamo8001\Project\Clustering\01
> Codes\testNum3.bat Process: C:\Users\mamo8001\Project\Clustering\01
> Codes\testNum4.bat Process: C:\Users\mamo8001\Project\Clustering\01
> Codes\testNum.bat Process: C:\Users\mamo8001\Project\Clustering\01
> Codes\testNum2.bat Process: C:\Users\mamo8001\Project\Clustering\01
> Codes\testNum3.bat Process: C:\Users\mamo8001\Project\Clustering\01
> Codes\testNum4.bat 
> All sub-processes completed 
> All sub-processes completed: [True, True, True, True, True, True, True,
> True]
> 
> Process finished with exit code 0

在打印最后两行时,我注意到日志文件没有打印出完整的数字列表,即批处理未完成

【问题讨论】:

    标签: python batch-file asynchronous multiprocessing


    【解决方案1】:

    问题是您的工作人员不会等待他们的子流程退出。在worker中的p = subprocess.Popen()调用之后添加p.wait()

    【讨论】:

      【解决方案2】:

      使用八个批处理文件,每个批处理文件只有一个 for 循环 到 40000,直到我将 Popen 作为上下文管理器运行。

      def worker(cmdlist, log):
          with open(log, 'w') as logfile:
              with subprocess.Popen(cmdlist, stderr=logfile, stdout=logfile) as p:
                  pass
          # return p.returncode
      

      然后最后两个打印语句直到所有 cmd 窗口都关闭后才打印。每个日志文件都有所有的数字以及循环的开始/结束行。

      作为上下文管理器,文档说 it 会一直等到进程完成。

      如果你有 Python 3.5+,文档说要使用 subprocess.run() 而不是 Popen.run() 文档明确表示它会等到命令完成 - 我无法测试,我有 Python 3.4。


      批处理文件是

      echo off
      
      echo Start of Loop
      for /L %%n in (1,1,40000) do echo %%n
      echo End of Loop
      

      【讨论】:

      • 谢谢@wwii,我在工作函数中缺少p.wait()。上下文管理器语法和run() 命令也会隐式地强制执行它。
      猜你喜欢
      • 2015-05-27
      • 2022-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多