在Python

时间:2015-06-06 16:45:21

标签: python arrays subprocess

我正在使用Python编写一个脚本,以这种方式打开多个子进程:

for file in os.listdir(FOLDER):
    subprocess.Popen(([myprocess]))

现在这个进程可以并行运行10-20个,每个进程都会在控制台中输出一个字符串行。我想要做的是将这些输出(无论以哪种顺序)附加到数组,并且当所有进程完成后,继续执行其他操作的脚本。

我不知道如何将每个输出附加到数组中,我想要检查是否所有子进程都已完成,我可以这样做:

outputs = []
k = len(os.listdir(FOLDER))
if len(outputs) == k 
 print "All processes are done!"

UPDATE!这段代码现在似乎有用了:

pids=set()
outputs = []
for file in os.listdir(FOLDER):
    p = subprocess.Popen(([args]), stdout=subprocess.PIPE)
    pids.add(p.pid)
while pids:
    pid,retval=os.wait()
    output = p.stdout.read()
    outputs.append(output)
    print('{p} finished'.format(p=pid))
    pids.remove(pid)

print "Done!"
print outputs

问题是outputs看起来像这样

>> Done!
>> ['OUTPUT1', '', '', '', '', '', '', '', '', '']

只填充第一个值,其他值为空,为什么?

2 个答案:

答案 0 :(得分:2)

  

我想要做的是将这些输出(无论以哪种顺序)附加到数组,并且当所有进程完成后,继续执行其他操作的脚本。

#!/usr/bin/env python
import os
from subprocess import Popen, PIPE

# start processes (run in parallel)
processes = [Popen(['command', os.path.join(FOLDER, filename)], stdout=PIPE)
             for filename in os.listdir(FOLDER)]
# collect output
lines = [p.communicate()[0] for p in processes]

要限制并发进程数,可以使用线程池:

#!/usr/bin/env python
import os
from multiprocessing.dummy import Pool, Lock
from subprocess import Popen, PIPE

def run(filename, lock=Lock()):
    with lock: # avoid various multithreading bugs related to subprocess
        p = Popen(['command', os.path.join(FOLDER, filename)], stdout=PIPE)
    return p.communicate()[0]

# no more than 20 concurrent calls
lines = Pool(20).map(run, os.listdir(FOLDER))

后一个代码示例也可以同时读取多个子进程,而前者基本上在相应的stdout OS管道缓冲区已满后序列化执行。

答案 1 :(得分:0)

您可以等到所有人完成工作,然后汇总他们的标准输出。要了解它是如何完成的,请参阅this answer,其中详细介绍了实施。

如果你需要异步执行,你应该为这个作业生成一个新线程,并在那个线程中等待。

如果您需要实时获得有关结果的通知,您可以单独为每个进程生成一个线程,在每个线程中等待它们,然后在它们完成后更新您的列表。

要阅读流程的输出,您可以使用subprocess.PIPE之类的#!/usr/bin/python2 import os import random import subprocess outputs = [] processes = [] for i in range(4): args = ['bash', '-c', 'sleep ' + str(random.randint(0, 3)) + '; whoami'] p = subprocess.Popen(args, stdout=subprocess.PIPE) processes.append(p) while processes: p = processes[0] p.wait() output = p.stdout.read() outputs.append(output) print('{p} finished'.format(p=p.pid)) os.sys.stdout.flush() processes.remove(p) print outputs

编辑这是一个适合我的完整示例:

mail()