2017-07-03 49 views
1

是否有一种简单的方式来收集子进程的输出而不实际等待呢?在Python中收集子进程输出非阻塞

我可以考虑创建一个subprocess.Popen()捕获它的标准输出,然后调用p.communicate(),但这会阻塞,直到子进程终止。

我能想到使用subprocess.check_output()或类似的,但也会阻止。

我需要一些东西,我可以开始,然后做其他的东西,然后检查子进程是否被终止,如果是,则取其输出。

我能想到的两个较为复杂的方式来实现这一目标:

  1. 将输出重定向到一个文件,然后终止后我可以读取该文件的输出。
  2. 实现并启动一个处理线程(!),它不断尝试从子进程的stdout读取数据并将其添加到缓冲区。

第一个需要临时文件和磁盘I/O,我不喜欢在我的情况。第二个意思是实现相当多。

我想可能有一种我现在还没有想到的更简单的方法,或者在某些我还没有找到的库中使用现成的解决方案。

+0

“进程中的一个线程”的方法并不复杂。你需要一个例子吗? –

回答

1

在线程中调用check_output有什么不对?

import threading,subprocess 

output = "" 

def f(): 
    global output 
    output = subprocess.check_output("ls") # ["cmd","/c","dir"] for windows 


t = threading.Thread(target=f) 
t.start() 
print('Started') 
t.join() 
print(output) 

注意,一个可能会倾向于使用p = subprocess.Popen(cmd,stdout=subprocess.PIPE),等待p.poll()是= None和尝试读取p.stdout算账:只有当输出是小作品,否则你会得到一个僵局,因为stdout缓冲区完整的,你必须不时阅读它。

使用p.stdout.readline()会起作用,但如果该过程没有定期打印,也会阻止。如果您的应用程序始终打印输出,则可以将其视为非阻塞,并且解决方案可以接受。

+0

我需要并行启动一堆进程。我不知道他们将以何种顺序完成,但我知道他们都在生产产量。每当完成时,我想收集它的输出并立即使用它。随着你的线程方法,我需要等待(任何出)一堆线程。我想我会使用Queue来做到这一点。但是这听起来相当复杂。并且为了让子进程和每个进程在主进程中有一个额外的线程,听起来就像将结构加倍一样。我认为,我宁愿去临时文件的方式。 – Alfe

+0

相关:https://stackoverflow.com/questions/375427/non-blocking-read-on-a-subprocess-pipe-in​​-python?rq = 1 –

0

我想你想要的是一个无缓冲的标准输出流。因此,您将能够捕获流程的输出而无需等待它完成。 您可以通过subprocess.Popen()函数和参数stdout=subprocess.PIPE来实现。

尝试这样的事情

proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) 

line = proc.stdout.readline() 
while line: 
    print line 
    line = proc.stdout.readline() 
+0

我需要有几个并行的,我不知道哪个将是多快,哪些将完成时。但是我想在子进程结束后立即使用子进程的输出。 – Alfe