0

我以这样一种方式定义了三个函数(两个循环),我想处理从 command_1 到 command_3 的文件块,一旦完成,返回使用相同的工作流程处理另一个块。

此处显示的伪代码

实际代码更长且有效:

def run(cmd):
  try:
    subprocess.Popen(command,shell='True')
  except:
    exit()

def run_chunk(chunk,command,flag=False)
  for file in chunk
    cmd = eval(command+'("' + bam + ')"') 
    run(cmd)
def main():
  chunks = [[chunk1],[chunk2]...]
  for chunk in chunks:
    run_chunk(chunk, command_1, True)
    os.waitpid(-1,0)
    run_chunk(chunk, command_2, True)
    os.waitpid(-1,0)
    run_chunk(chunk, command_3, True)
    os.waitpid(-1,0)

注意:eval 将返回一个字符串,它是“运行”函数的命令

我的问题是,当我运行 command_1 时,os.waitpid() 似乎工作;一旦 command_1 完成,程序转到 command_2,在我看来,command_2 会在转到 command_3 之前等待自己,但是主函数中的外循环将立即执行 command_1(我不想要)

任何人都可以发现代码中的任何错误吗?非常感谢!

4

2 回答 2

1

每次调用都run_chunk可能产生许多子子进程。os.waitpid(-1, 0)将等待任何子子进程结束。如果 中有很多文件chunk,则将在所有子子进程完成os.waitpid(-1, 0)之前返回。因此,后续调用可能发生得太早。run_chunk

如果您希望每个调用run按顺序发生,请添加对proc.communicate()in的调用run

def run(cmd):
    try:
        proc = subprocess.Popen(cmd, shell=True)
        proc.communicate()
    except:
        exit()

如果您希望所有对run生成的调用run_chunk同时发生,那么也许最简单的方法是使用多处理 ThreadPool

import multiprocessing.pool as mpool

def run(cmd):
    try:
        proc = subprocess.Popen(cmd, shell=True)
        proc.communicate()
    except:
        exit()

def run_chunk(chunk, command, flag=False):
    for file in chunk:
        cmd = eval(command + '("' + bam + ')"')
        pool.apply_async(run, args=(cmd,))
    pool.join()  # wait until all the calls to run have completed.

def main():
    chunks = [[chunk1], [chunk2]...]
    for chunk in chunks:
        run_chunk(chunk, command_1, True)
        run_chunk(chunk, command_2, True)
        run_chunk(chunk, command_3, True)

if __name__ == '__main__':
    pool = mpool.ThreadPool() 

我在这里选择使用 ThreadPool 而不是常规的多处理池,因为池中的每个工作人员只调用subprocess.Popen,这反过来又产生了一个新的子进程。池中的工作人员只是等待该子进程完成。所以在自己的子进程中运行工人似乎是一种浪费。我认为更轻的线程就可以了。

如果您在实例化时没有指定数字mpool.ThreadPool,那么您将获得一个池,其中包含与 CPU 内核一样多的工作线程。这听起来对我来说是最优的,因为每个工作线程都会产生一个自然需要核心的子进程。因此,拥有比核心更多的工作线程(以及因此更多的子进程)是有意义的,因为多余的子进程无论如何都必须等待可用的核心。

于 2013-07-01T17:35:50.390 回答
1

通过查看API,我认为问题可能与您等待子进程的方式有关。我建议实际上尝试等待孩子的特定 pid ( waitpid(child1) )。您可以从 Popen 调用中获取该信息。

如果 pid 大于 0,waitpid() 请求该特定进程的状态信息。如果 pid 为 0,则请求当前进程的进程组中任何子进程的状态。如果 pid 为 -1,则请求属于当前进程的任何子进程。如果 pid 小于 -1,则为进程组 -pid(pid 的绝对值)中的任何进程请求状态。

于 2013-07-01T17:33:53.557 回答