带有池/队列的Python多个子进程完成后立即恢复输出,并启动队列中的下一个作业

带有池/队列的Python多个子进程完成后立即恢复输出,并启动队列中的下一个作业,python,parallel-processing,queue,subprocess,stdout,Python,Parallel Processing,Queue,Subprocess,Stdout,我目前正在启动一个子进程,并在运行中解析stdout,而不必等待它完成对stdout的解析 for sample in all_samples: my_tool_subprocess = subprocess.Popen('mytool {}'.format(sample),shell=True, stdout=subprocess.PIPE) line = True while line: myline = my_tool_subprocess.stdo

我目前正在启动一个子进程,并在运行中解析stdout,而不必等待它完成对stdout的解析

for sample in all_samples:
    my_tool_subprocess = subprocess.Popen('mytool {}'.format(sample),shell=True, stdout=subprocess.PIPE)
    line = True
    while line:
        myline = my_tool_subprocess.stdout.readline()
        #here I parse stdout..
在我的脚本中,我多次执行此操作,具体取决于输入样本的数量

这里的主要问题是,每个子流程都是一个程序/工具,在运行时100%使用1个CPU。这需要一些时间。。每次输入大约20-40分钟

我想要实现的是,设置一个池,队列(我不确定这里的确切术语是什么)来同时运行N max子进程作业进程。所以我可以最大限度地提高性能,而不是按顺序进行

因此,执行流(例如最大4个作业池)应为:

  • 启动4个子流程
  • 当其中一个作业完成时,解析stdout并启动next
  • 执行此操作直到队列中的所有作业都完成
如果我能做到这一点,我真的不知道如何确定哪个示例子流程是已经完成的。现在,我不需要识别它们,因为每个子进程都是按顺序运行的,并且我在子进程打印标准输出时解析标准输出


这非常重要,因为我需要识别每个子流程的输出,并将其分配给相应的输入/样本。

正如我理解您的问题一样,您的问题是,第一个流程完成后的结果将提供给第二个流程,然后再提供给第三个流程,依此类推, 要实现这一点,您应该导入threading模块并使用Thread类:

proc = threading.Thread(target=func, args=(func arguments) # Thread class
proc.start()                                   # starting the thread
proc.join()                                    # this ensures that the next thread does no 

开始,直到前一个线程完成。…

如果是这种情况,您应该在不使用
proc.join()的情况下编写上面相同的代码。
在这种情况下,主线程(main)将启动其他四个线程,这种情况下,在单个进程中进行多线程处理(换句话说,多核处理器没有任何好处) 要从多核处理器中获益,您应使用如下多处理模块:

proc = multiprocessing.Process(target=func, args=(funarguments))      
proc.start()

这样,每个进程都将是一个单独的进程,并且单独的进程可以彼此完全独立运行

线程池
可能非常适合您的问题,您可以设置工作线程的数量并添加作业,线程将以自己的方式完成所有任务

from multiprocessing.pool import ThreadPool
import subprocess


def work(sample):
    my_tool_subprocess = subprocess.Popen('mytool {}'.format(sample),shell=True, stdout=subprocess.PIPE)
    line = True
    while line:
        myline = my_tool_subprocess.stdout.readline()
        #here I parse stdout..


num = None  # set to the number of workers you want (it defaults to the cpu count of your machine)
tp = ThreadPool(num)
for sample in all_samples:
    tp.apply_async(work, (sample,))

tp.close()
tp.join()

不是真的。我的意思是每个过程的输入都会产生一个输出。我不需要处理上一个进程的输出来计算下一个进程的输出。这就是为什么我希望能够并行运行它们。现在的问题是,我以顺序的方式一个接一个地运行它们。这会带来好处,因为子进程在不同的进程中(python线程只是在等待输出)哇!这似乎正是我所需要的。如果将来我在work()中使用的工具可以从多个核心中受益,那么我可以在每个创建的线程中使用2个CPU(核心),有没有办法控制它不超过计算机的核心数?(即:当我的机器只有8个内核时,我产生了4个线程,每个线程使用4个内核。)@gmarco这不能告诉任何工作类型,或者它使用/需要多少内核。如果不指定
ThreadPool
(第一个参数)的线程数,它将使用函数
multiprocessing.cpu\u count()
来获取cpu计数,并旋转那么多线程。因此,如果您知道每个作业需要多少个内核,您可以自己计算(
ThreadPool(multiprocessing.cpu\u count()/2)
)谢谢!我对子流程有一些严重的问题。由于某种原因,Popen没有启动,通常也不为我工作,我只是切换到
ThreadPool
+
os.system()
,它甚至比Popen想象的更好@ÍhorMé您最好使用子流程。但如果有太多的输出,并且没有处理stdout/err properlysubprocess,则可以将其死锁。出于某种原因,Subprocess没有生成线程。我没有找到解决那个问题的办法。可能是什么虫子。(不在我这边)