subprocess.run输出为空(Python 3.8)

6
我试图使用以下代码捕获命令的输出:
lines = subprocess.run(['ffmpeg', '-hide_banner', '-nostats', '-i', in_filename, '-vn', '-af', 'silencedetect=n={}:d={}'.format(silence_threshold, silence_duration), '-f', 'null', '-'], capture_output=True, text=True, shell=True, check=True, encoding='utf-8').stdout 
print (lines)

但是lines是个空字符串,输出为空。 当删除capture_output=True时,将会显示正确的输出(但不打印)。
我尝试了许多组合,包括删除所有subprocess.run参数,仅保留capture_output=True参数,结果仍然相同。
我还使用了少量参数进行最小示例测试:subprocess.run(['ffmpeg', '-version'], capture_output=True, text=True, shell=True, check=True, encoding='utf-8').stdout 另外,我也测试了将stdout=subprocess.PIPEstderr=subprocess.PIPE作为subprocess.run参数,而不是capture_output=True.
我无法弄清楚到底发生了什么。提前感谢!

1
你是否尝试过 subprocess 中的 check_output()subprocess.Popen().communicate()?请参考这个答案 - thuyein
根据Python文档,我猜测subprocess.run应该是首选的方法。无论如何,当我使用subprocess中的check_output()时总是会遇到问题。 - Marino Linaje
1个回答

3
默认情况下,ffmpeg将日志记录到stderr。您使用capture_output=True,因此run()函数将捕获stdoutstderr值。
问题1)行是空字符串,没有打印任何内容。
回答1)这是正常的,因为默认情况下ffmpeg不会记录到stdout
问题2)当删除capture_output=True时,将显示正确的输出(而不打印它)。
A-2) 这正是我们预期的结果。当你移除 capture_output=True 时,ffmpeg 将日志记录到标准错误流(默认情况下为终端/控制台),你将在屏幕上看到 ffmpeg 的输出(stdin,stdout 和 stderr 这些 通常与用户的终端相关联)。当你使用 capture_output=True 时,ffmpeg 的日志将被发送到内存中的内核 pipe 文件对象中(在 Unix 和 Linux 中,对于 Windows 系统不适用)。这就是为什么没有 print() 捕获到的标准输出流时,你在终端/控制台上看不到任何输出的原因。 subprocess.run() 函数将返回 CompletedProcess(process.args, retcode, stdout, stderr) 实例,你可以获取 stdout 属性的值,但我们不需要它,我们需要 stderr 属性的值,因为如上所述,ffmpeg 默认将日志记录到 stderr 中。
你需要进行修改,例如:
lines = subprocess.run(['ffmpeg', '-hide_banner', '-nostats', '-i', in_filename, '-vn', '-af', 'silencedetect=n={}:d={}'.format(silence_threshold, silence_duration), '-f', 'null', '-'], capture_output=True, text=True, shell=True, check=True, encoding='utf-8').stderr
print (lines)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接