捕获 subprocess.run() 的输出并实时打印它?

16 python subprocess

我想使用运行命令subprocess.run(),然后将其 stdout/stderr 作为字符串获取,但我希望子进程在运行时也能正常将其输出打印到控制台。如果我做

result = subprocess.run(['ls', '-al'])
Run Code Online (Sandbox Code Playgroud)

然后我可以看到打印到控制台的输出,但在命令运行后我无法访问输出。如果我做

result = subprocess.run(['ls', '-al'], capture_output=True, text=True)
Run Code Online (Sandbox Code Playgroud)

我可以访问result.stdoutresult.stderr但在命令运行时控制台上没有打印任何内容。我可以同时打印到控制台并保存到吗result.stdout

Len*_*mju 3

来自以下文档subprocess.run

\n
\n

运行 args 描述的命令。等待命令完成,然后返回 CompletedProcess 实例。
\n[...]
\n如果capture_output为 true,则将捕获 stdout 和 stderr。stdout=PIPE使用时,会使用和自动创建内部 Popen 对象stderr=PIPE

\n
\n

文档subprocess.PIPE说:

\n
\n

可以用作Popen的stdinstdoutstderr参数的特殊值,并指示应打开到标准流的管道。对于 Popen.communicate() 最有用。

\n
\n

Popen 构造函数参数的文档stdout

\n
\n

stdin、stdout 和 stderr 分别指定执行的程序\xe2\x80\x99 的标准输入、标准输出和标准错误文件句柄。有效值为 PIPE、DEVNULL、现有文件描述符(正整数)、现有文件对象None

\n
\n

因此,使用capture_output=True是不行的,因为输出将存储在管道中供您在调用完成后读取。

\n

subprocess.Popen更简单的是您可以按照@MatBBastos的建议使用communicate(重复将内容发送到stdin并从stdout / stderr接收内容)。链接的解决方案有点过时(参见其自己的评论;Python 2),但应该运行良好。一个相关的解决方案是这个。

\n

要继续使用subprocess.run,您必须提供一个文件描述符作为stdout参数,我不知道如何重定向到执行您想要的操作的文件对象:写入标准流,但也在内存中保留副本供以后使用。\ nio
模块中有文档,并且 Stack Overflow 上有很多关于执行此类操作的问题,但它明显比其他方式更困难。

\n