3

所以我试图将 HandBrakeCLI 的输出捕获为 Python 子进程。这不是 stderr 的问题,因为每次更新都会在类似文件的管道中创建一个新行。但是,使用标准输出,HandBrakeCLI 会进行就地更新,我很难捕获它们。我什至不知道就地更新被称为什么,这使得查找相关提示有点棘手。

到目前为止,我提出的唯一解决方案是将标准输出写入实际文件并从中读取,但我宁愿以理智的方式(在内存中)这样做。

COMMAND = ['HandBrakeCLI', '-v', '-i', 'in.m4v', '-o', 'out.m4v', '-Z', 'Normal']

outfile = open('output.txt', 'w')

proc = subprocess.Popen(COMMAND, stdout=outfile, stderr=subprocess.PIPE)

infile = open('output.txt', 'r')

while proc.poll() is None:
    print infile.read()
    infile.seek(0)

这行得通,但必须有更好的方法。当尝试使用communicate() 或只是简单的proc.stdout.read() 时,我什么也得不到。

我究竟做错了什么?谢谢!

更新

根据@wim 的建议,我检查了 HandBrakeCLI 提供的原始输出,它看起来像这样:

\rEncoding: task 1 of 1, 0.15 %

处理前缀为 \r 的标准输出的最佳方法是什么?

4

1 回答 1

5

我认为我上面关于使用universal_newlines=True 的评论会起作用。

这是一个示例就地编写器,称为“inplace_output.py”

import sys
import time


def main():
    for k in range(5):
        print "{0:03d}\r".format(k),
        sys.stdout.flush()
        time.sleep(1)

if __name__ == "__main__":
    main()

您可以运行它,并观察它写入 000,然后是 001,依此类推,每次都覆盖之前的输出。

这是一个将上述内容作为子进程运行的脚本,并逐行读取其输出:

import subprocess


cmd = ['python', 'inplace_output.py']

proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, universal_newlines=True)

while True:
    out = proc.stdout.readline()
    print repr(out)
    if len(out) == 0:
        break

如果想在子进程程序终止时一次收集所有输出,可以将 while 循环替换为,例如,

out, err = proc.communicate()
lines = out.splitlines()

这些对你有用吗?

于 2012-09-04T03:19:25.280 回答