Python子进程在进程完成时获取输出

时间:2013-08-16 02:40:55

标签: python operating-system subprocess popen

目前我通过蓝牙从设备获取MAC地址,并且我将这些mac地址一次传递给一个调用子进程并将输出分配给变量的方法。使用该变量,我运行一些过滤函数,以从子进程中调用的命令中获取值。然后,如果它从输出中找到它,则返回该值。

我想要做的是立即将所有mac地址传递给方法并一次运行它们。如何在进程完成时捕获每个进程的输出并运行我的过滤脚本,同时通知我进程是否失败或错误。

以下是一次处理一个mac的当前方法。让我们假设我正在传递一个mac地址列表。

 def getchan(mac):
  a = subprocess.Popen(["sdptool", "search","--bdaddr", mac, "OPUSH"], stdout = subprocess.PIPE).communicate()[0].split()[2:]
  if a==[]:
      print "ERROR"
      return "ERROR"
  else:
      count = 0
      for item in a:
          if item == "Channel:":
              return a[count + 1]
          count += 1
      return "Could not find the OPUSH channel"

应该看起来像

def getchan(macs):
processes = set()
for mac in macs:
  processes.add(subprocess.Popen(["sdptool", "search","--bdaddr", mac, "OPUSH"], stdout =      subprocess.PIPE).communicate()[0].split()[2:])
  #this is where I need the help

谢谢你看看。任何对子流程的帮助或澄清将不胜感激。

2 个答案:

答案 0 :(得分:1)

import select
import subprocess

def in_parallel(processes):
    pipes = {p.stdout.fileno(): (i, p.stdout) for i, p in enumerate(processes)}

    poller = select.poll()
    for fd, pipe in pipes.iteritems():
        poller.register(fd, select.POLLIN)

    outputs = [''] * len(processes)

    while pipes:
        active = poller.poll()
        for fd, event in active:
            idx, pipe = pipes[fd]
            o = pipe.read()
            if o:
                outputs[idx] += o
            else:
                poller.unregister(fd)
                pipe.close()
                del pipes[fd]

    for p in processes:
        p.wait()

    return outputs

args = ['a', 'b', 'c']
processes = [subprocess.Popen(['sleep 5; echo ' + arg], stdout=subprocess.PIPE, shell=True) for arg in args]
outputs = in_parallel(processes)
print outputs

$ time python test.py
['a\n', 'b\n', 'c\n']

real    0m5.042s
user    0m0.016s
sys 0m0.016s

答案 1 :(得分:0)

以可移植的方式并行获取子进程输出的最简单方法是使用线程:

from multiprocessing.dummy import Pool # use threads
from subprocess import check_output

def getchan_mp(mac):
    try:
        output = check_output(["sdptool", "search","--bdaddr", mac, "OPUSH"])
        result = parse(output)
        return result, mac, None
    except Exception as err:
        return None, mac, err

results = Pool(processes=len(macs)).map(getchan_mp, macs)
failed_macs = [mac for result, mac, error in results if error is not None]