难以捕获执行就地状态更新的子流程的输出 [英] Having difficulty capturing output of a subprocess that does in-place status updates

查看:25
本文介绍了难以捕获执行就地状态更新的子流程的输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

So I'm trying to capture the output of HandBrakeCLI as a Python subprocess. This is not a problem with stderr as each update creates a new line in the file-like pipe. However, with stdout, HandBrakeCLI makes in-place updates and I'm having difficulty capturing them. I'm not even ure what the in-place updates are called, which makes finding relevant tips a bit tricky.

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

The only solution I've come up with thus far is to write the stdout to an actual file and read from that, but I'd rather do this the sane way (in memory).

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)

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

This works, but there must be a better way. When attempting to use communicate() or just plain proc.stdout.read() I get nothing.

我做错了什么?谢谢!

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

Per @wim suggestion I checked to see what the raw output HandBrakeCLI provided and it looked something like this:

\rEncoding: task 1 of 1, 0.15 %

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

What is the best way to handle a stdout that is prefixed with a \r?

推荐答案

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

I think the comment I made above about using universal_newlines=True will work.

这是一个示例就地编写器,名为inplace_output.py"

Here's a sample in-place writer, called "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 等,每次覆盖之前的输出.

You can run that, and watch it write 000, then 001, etc, each time overwriting the previous output.

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

Here's a script that runs the above as a subprocess, and reads its output line by line:

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循环替换为,例如

If want to collect all the output at once when the subprocess program terminates, you can replace the while loop with, say,

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

这些对你有用吗?

这篇关于难以捕获执行就地状态更新的子流程的输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆