要从我的python脚本启动程序,我使用以下方法:

def execute(command):
    process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    output = process.communicate()[0]
    exitCode = process.returncode

    if (exitCode == 0):
        return output
    else:
        raise ProcessException(command, exitCode, output)

所以当我启动一个进程,比如进程。执行("mvn clean install")时,我的程序会一直等待,直到进程完成,只有到那时我才能得到程序的完整输出。这是恼人的,如果我正在运行一个进程,需要一段时间才能完成。

我能让我的程序一行一行地写进程输出吗,在循环结束之前轮询进程输出什么的?

我找到了这篇文章,可能与此有关。


当前回答

对于试图回答这个问题并从Python脚本中获取标准输出的人来说,请注意Python会缓冲它的标准输出,因此可能需要一段时间才能看到标准输出。

这可以通过在目标脚本中的每个标准输出写入后添加以下内容来纠正:

sys.stdout.flush()

其他回答

好吧,我设法解决它没有线程(任何建议,为什么使用线程会更好,感谢)使用从这个问题的一个片段拦截一个子进程的标准输出,而它正在运行

def execute(command):
    process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

    # Poll process for new output until finished
    while True:
        nextline = process.stdout.readline()
        if nextline == '' and process.poll() is not None:
            break
        sys.stdout.write(nextline)
        sys.stdout.flush()

    output = process.communicate()[0]
    exitCode = process.returncode

    if (exitCode == 0):
        return output
    else:
        raise ProcessException(command, exitCode, output)

在Python中>= 3.5使用subprocess.run为我工作:

import subprocess

cmd = 'echo foo; sleep 1; echo foo; sleep 2; echo foo'
subprocess.run(cmd, shell=True)

(在没有shell=True的情况下,在执行过程中获得输出也可以工作) https://docs.python.org/3/library/subprocess.html#subprocess.run

如果您想在进程运行时从stdout打印,请使用-u Python选项和subprocess.Popen()。(shell=True是必要的,尽管有风险…)

要回答最初的问题,IMO的最佳方法是直接将子进程stdout重定向到程序的stdout(可选地,对于stderr也可以这样做,如下例所示)

p = Popen(cmd, stdout=sys.stdout, stderr=sys.stderr)
p.communicate()

@tokland

尝试了你的代码,并针对3.4和Windows进行了修正 dir。CMD是一个简单的dir命令,保存为CMD -file

import subprocess
c = "dir.cmd"

def execute(command):
    popen = subprocess.Popen(command, stdout=subprocess.PIPE,bufsize=1)
    lines_iterator = iter(popen.stdout.readline, b"")
    while popen.poll() is None:
        for line in lines_iterator:
            nline = line.rstrip()
            print(nline.decode("latin"), end = "\r\n",flush =True) # yield line

execute(c)