Python多进程不等待

1 投票
2 回答
1543 浏览
提问于 2025-04-18 04:58

我现在正在使用多进程功能来分析大约10个文件。

不过,我只想每次运行5个进程。

当我尝试这样做时,它并没有按我想的那样工作。创建的进程数量超过了我指定的数量。有没有简单的方法可以限制进程数量到5个?(Windows 7 / Python 2.7)

编辑: 我担心你们的解决方案还是不管用。我会尝试在这里提供更多细节;

主Python文件;

import python1
import python2 
import multiprocessing

# parallel = [fname1, fname2, fname3, fname4, fname5, fname6, fname7, fname8, fname9, fname10]
if name == '__main__':
   pool = multiprocessing.Pool(processes=max(len(parallel), 5))
   print pool.map(python1.worker, parallel)   

Python1文件;

import os
import time
import subprocess

def worker(sample):
    command = 'perl '+sample[1].split('data_')[0]+'methods_FastQC\\fastqc '+sample[1]+'\\'+sample[0]+'\\'+sample[0]+' --outdir='+sample[1]+'\\_IlluminaResults\\_fastqcAnalysis'
    subprocess.call(command)
    return sample

12个文件的返回结果在所有打开的perl模块关闭之前就回来了。而且打开的perl进程有12个,而不是最多5个。(图片;你可以清楚地看到返回结果在perl命令完成之前就回来了,而且进程数量超过了5个 http://oi57.tinypic.com/126a8ht.jpg

2 个回答

0

我在Linux系统下用python-2.7试了以下代码,但它没有产生预期的效果。一次只创建了5个进程。

import os
import multiprocessing
import psutil
from functools import partial

def worker(pid, filename):
#    assert len(psutil.Process(pid).children(recursive=True)) == 5  # for psutil-2.x
    assert len(psutil.Process(pid).get_children(recursive=True)) == 5
    print(filename)

parallel = range(0, 15)

if __name__ == '__main__':
#    with multiprocessing.Pool(processes=5) as pool:  # if you use python-3
    pool = multiprocessing.Pool(processes=min(len(parallel), 5))
    pool.map(partial(worker, os.getpid()), parallel)

当然,如果你在工作函数里使用os.system(),它会创建额外的进程,这样进程的结构就会变得复杂(这里用os.system('sleep 1')作为例子)。

\_ python2.7 ./test02.py
    \_ python2.7 ./test02.py
    |   \_ sh -c sleep 1
    |       \_ sleep 1
    \_ python2.7 ./test02.py
    |   \_ sh -c sleep 1
    |       \_ sleep 1
    \_ python2.7 ./test02.py
    |   \_ sh -c sleep 1
    |       \_ sleep 1
    \_ python2.7 ./test02.py
    |   \_ sh -c sleep 1
    |       \_ sleep 1
    \_ python2.7 ./test02.py
        \_ sh -c sleep 1
            \_ sleep 1
0

我不知道为什么具体发生了什么和没有发生什么是个秘密。

提供一个SSCCE意味着要有一个实际能运行的程序。(比如看看worker()这个函数,它接收一个file参数,但这个参数从来没有被使用,而command变量又没有定义过。)

但我觉得关键在于你的fileX只是文件名,它们被尝试执行。

把你的函数改成

def worker(filename):
    command = "echo X " + filename + " Y"
    os.system(command)

这样应该就能正常工作了。(注意我把file改成了filename,这样就不会和内置名称冲突了。)

顺便说一下,建议你用subprocess模块来替代os.system()

在这种情况下,你可以这样做

import subprocess

def worker(filename):
    command = ["echo", "X", filename, "Y"]
    subprocess.call(command)

这样应该效果是一样的。

另外,从风格上讲:

pool = multiprocessing.Pool(processes=max(len(parallel), 5))

这样更简单,也能达到同样的效果。


你的修改让问题变得更清楚了。

看起来由于某些未知原因,你的perl程序比预期的提前结束了。我不知道为什么会这样——也许它们自己创建了另一个进程,然后立刻退出。或者是因为Windows系统的一些奇怪情况。

一旦多进程池发现一个子进程声称已经完成,它就准备好启动另一个进程。

所以正确的做法是找出为什么perl程序没有按预期工作。

撰写回答