Python多进程不等待
我现在正在使用多进程功能来分析大约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 个回答
我在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
我不知道为什么具体发生了什么和没有发生什么是个秘密。
提供一个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程序没有按预期工作。