在Python

时间:2017-07-03 11:21:09

标签: python subprocess blocking

是否有一种简单的方法来收集子进程的输出而不实际等待它?

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

我可以考虑使用subprocess.check_output()或类似的,但也会阻止。

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

我可以想到两种相当复杂的方法来实现这个目标:

  1. 将输出重定向到文件,然后在终止后,我可以读取该文件的输出。
  2. 实现并启动一个处理程序线程(!),它不断尝试从子进程的stdout读取数据并将其添加到缓冲区。
  3. 第一个需要临时文件和磁盘I / O,在我的情况下我并不喜欢。第二个意味着实施相当多。

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

2 个答案:

答案 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()会起作用,但如果流程不定期打印,也会阻止。如果您的应用程序一直打印到输出,那么您可以将其视为非阻塞,并且解决方案是可接受的。

答案 1 :(得分:0)

我认为你想要的是一个无缓冲的stdout流。 有了它,您将能够捕获过程的输出而无需等待它完成。 您可以使用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()