【问题标题】:Python Subprocess Batch CallPython 子进程批量调用
【发布时间】:2015-09-15 20:43:29
【问题描述】:

我正在尝试创建一个可变的批量大小,以进行子流程调用。我对启动一批 5 个的最佳方式有点困惑,等待所有 5 个完成而不是启动下一个 5 个。

到目前为止我所拥有的是:

batchSize = 5
proccessArray = process.split(",")
processLength = len(proccessArray) - 1
counter1 = 0
for i in range(0, processLength, batchSize):
    for x in range(1, batchSize):
        d = {}
        if counter1 < processLength:
            dgclOutput = inputPath + st + "_" + (i + x) + "output"
            d["process{0}".format(x)] = subprocess.Popen(proccessArray(i + x) + ">>" + dgclOutput, shell=True, stdout=subprocess.PIPE)
            counter1 + 1
        else:
            break

BatchSize 是我一次要处理的批次数。 Process Array 是它需要调用的命令列表。进程长度是可能的命令的数量。当计数器达到最大值时,计数器将退出循环。

所以我的第一个循环是批量大小的数量,而不是在字典中创建 5 个子进程的内部循环开始。

此代码不起作用,有人知道如何使它起作用或更好的解决方案吗?

【问题讨论】:

  • 您实际上并没有在此代码中等待任何进程完成。

标签: python subprocess


【解决方案1】:

我认为您可能正在寻找以下方面的内容:

batchSize = 5
processArray = process.split(",")
for i in xrange(0, len(processArray), batchSize):
    batch = processArray[i:i+batchSize]  # len(batch) <= batchSize
    ps = []
    for process in batch:
        output = "..."
        p = subprocess.Popen(process + ">>" + output, shell=True, stdout=subprocess.PIPE)
        ps.append(p)
    for p in ps:
        p.wait()

【讨论】:

    【解决方案2】:

    你想做这样的事情。假设您有一个列表,commands,其中包含您要运行的所有命令。

    def chunks(l, n):
        """Yield successive n-sized chunks from l."""
        for i in xrange(0, len(l), n):
            yield l[i:i+n]
    
    for next_batch in chunks(commands, 5):
        # Start the next few subprocesses
        subps = [subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
                 for cmd in next_batch]
        # Wait for these to finish
        for subp in subps:
            subp.wait()
    

    (采用块函数from this answer。)

    【讨论】:

    • 除非您从管道中读取,否则不要使用 stdout=PIPE。 OP 可能想要在这里模拟stdout=open(dgclOutput, 'a')。此外,不鼓励shell=True。否则,chunks() 是这里的正确方法。
    【解决方案3】:

    您需要subprocess 模块的.communicate().wait() 函数来等待进程完成。或者,您可以使用.poll() 查看子进程是否已完成。

    batchSize = 5
    proccessArray = process.split(",")
    processLength = len(proccessArray) - 1
    counter1 = batchSize
    for i in range(0, processLength, batchSize):
        d = {}
        for x in range(1, batchSize):
            dgclOutput = inputPath + st + "_" + (i + x) + "output"
            d["process{0}".format(x)] = subprocess.Popen(proccessArray(i + x) + ">>" + dgclOutput, shell=True, stdout=subprocess.PIPE)
        while not counter1:
            for p in d:
                if not p.poll():
                   counter1 -= 1
    

    这里有一个更好的例子:Python subprocess in parallel

    【讨论】:

      猜你喜欢
      • 2015-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-08
      • 1970-01-01
      • 2016-02-12
      • 2014-01-24
      • 2015-07-18
      相关资源
      最近更新 更多