在进程运行时不断打印子进程输出

2024-03-28 21:27:55 发布

您现在位置:Python中文网/ 问答频道 /正文

要从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)

因此,当我启动一个像Process.execute("mvn clean install")这样的进程时,我的程序会等到进程完成,然后才得到程序的完整输出。如果我正在运行一个需要一段时间才能完成的进程,这很烦人

我可以让我的程序通过在循环或其他过程结束之前轮询过程输出,逐行写入过程输出吗

我找到了this篇可能相关的文章


Tags: 方法程序脚本trueoutputexecute进程过程
3条回答

好的,我通过使用这个问题的一个片段Intercepting stdout of a subprocess while it is running在没有线程的情况下解决了这个问题(任何关于为什么使用线程会更好的建议都会受到赞赏)

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)

只要命令输出行,您就可以使用iter处理这些行:lines = iter(fd.readline, "")。下面是一个完整的示例,展示了一个典型的用例(感谢@jfs的帮助):

from __future__ import print_function # Only Python 2.x
import subprocess

def execute(cmd):
    popen = subprocess.Popen(cmd, stdout=subprocess.PIPE, universal_newlines=True)
    for stdout_line in iter(popen.stdout.readline, ""):
        yield stdout_line 
    popen.stdout.close()
    return_code = popen.wait()
    if return_code:
        raise subprocess.CalledProcessError(return_code, cmd)

# Example
for path in execute(["locate", "a"]):
    print(path, end="")

要在Python 3中刷新子进程的标准输出缓冲区后立即逐行打印子进程的输出,请执行以下操作:

from subprocess import Popen, PIPE, CalledProcessError

with Popen(cmd, stdout=PIPE, bufsize=1, universal_newlines=True) as p:
    for line in p.stdout:
        print(line, end='') # process line here

if p.returncode != 0:
    raise CalledProcessError(p.returncode, p.args)

注意:您不需要p.poll()——循环在达到eof时结束。而且您不需要iter(p.stdout.readline, '')——预读错误在Python3中已经修复

另见,Python: read streaming input from subprocess.communicate()

相关问题 更多 >