捕获subprocess.run()的输出,但还要实时打印它



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

result = subprocess.run(['ls', '-al'])

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

result = subprocess.run(['ls', '-al'], capture_output=True, text=True)

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

来自subprocess.run:的文档

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

subprocess.PIPE的文档说:

特殊值,可用作Popen的stdintdoutstderr参数,指示应打开通往标准流的管道。Popen.communicate((.最有用

Popen构造函数参数stdout:的文档

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

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

更简单的方法是按照@MatBBastos的建议使用subprocess.Popen,使用它可以communicate(重复向stdin发送内容,并从stdout/tderr接收内容(。链接的解决方案有点过时(参见它自己的评论;Python 2(,但应该可以很好地工作。一个相关的解决方案就是这个。

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

最新更新