我有三个函数(两个循环)定义,我想从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将返回一个字符串,这是“run”函数的命令
我的问题是,当我运行command_1时,os.waitpid()似乎正在运行;一旦command_1完成,程序进入command_2,在我看来command_2将在转到command_3之前等待,但main函数中的外部循环将立即执行command_1(我不想要)
有人能发现代码中的任何错误吗? 非常感谢!
答案 0 :(得分:1)
通过查看API,我认为问题可能与您等待子进程的方式有关。我建议实际上尝试等待孩子的特定pid( waitpid(child1))。您可以从Popen电话中获取该信息。
如果pid大于0,则waitpid()请求该特定进程的状态信息。如果pid为0,则请求是针对当前进程的进程组中的任何子进程的状态。如果pid为-1,则该请求与当前进程的任何子进程有关。如果pid小于-1,则为进程组中的任何进程请求状态-pid(pid的绝对值)。
答案 1 :(得分:1)
每次调用run_chunk
都可能会产生许多子子进程。 os.waitpid(-1, 0)
将等待任何子子进程结束。如果chunk
中有多个文件,那么os.waitpid(-1, 0)
将在所有子项子进程完成之前返回。因此,对run_chunk
的后续调用可能会过早发生。
如果您希望每次调用run
按顺序发生,请在proc.communicate()
中添加对run
的调用:
def run(cmd):
try:
proc = subprocess.Popen(cmd, shell=True)
proc.communicate()
except:
exit()
如果您希望run
生成的所有run_chunk
来电同时发生,那么最简单的方法就是使用multiprocessing 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
,这反过来会产生一个新的子进程。池中的worker只是等待该子进程完成。因此,在自己的子流程中运行worker似乎是一种浪费。我认为一个重量更轻的线程就可以了。
如果在实例化mpool.ThreadPool
时没有指定数字,那么您将获得一个拥有与CPU内核一样多的工作线程的池。这对我来说听起来是最理想的,因为每个工作线程都会产生一个自然需要核心的子进程。因此,有更多的工作线程(因此更多的子进程)比核心更重要,因为剩余的子进程只需要等待可用的核心。