捕获通用换行符但保留原始

时间:2019-06-23 06:03:41

标签: python subprocess

这是我的问题,

我正在尝试制作一个简单的程序,该程序使用Python的subprocess模块运行另一个进程,我想捕获该进程的实时输出。

我知道可以这样做:

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

for line in iter(proc.stdout.readline, ""):
    line = line.rstrip()
    if line != "":
        print(line)

问题是,该进程可能生成带有回车符\r的输出,并且我想在程序中模拟该行为。

如果我在universal_newlines中使用Popen标志,那么我可以捕获用回车符生成的输出,但是我不知道是这样,所以我只能打印用换行符“定期”进行。我想避免这种情况,因为这可能会产生很多输出。

我的问题基本上是,我是否可以像\r一样捕获\n输出,但将其与实际\n输出区分

编辑

这是我尝试过的一些简化代码:

文件download.py

import subprocess

try:
    subprocess.check_call(
        [
            "aws",
            "s3",
            "cp",
            "S3_LINK",
            "TARGET",
        ]
    )

except subprocess.CalledProcessError as err:
    print(err)
    raise SystemExit(1)

文件process_runner.py

import os
import sys

import subprocess

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

for char in iter(lambda: proc.stdout.read(1), ""):
    sys.stdout.write(char)

download中的代码使用aws s3 cp,它返回下载进度的回车符。我想在程序process_runner中模拟输出的这种行为,该程序接收download的输出。

起初,我尝试迭代readline而不是read(1)。由于CR被忽略,因此无法正常工作。

1 个答案:

答案 0 :(得分:2)

一种可能的方法是通过既不指定encoding也不指定error,当然也不要指定universal_newline来使用Popen的二进制接口。然后,我们可以在二进制流中使用TextIOWrappernewline='' 一起使用。因为TextIOWrapper的文档说:

  

...如果换行符是None ...如果它是'',则启用通用换行符模式,但行尾未翻译后返回给呼叫者

(符合PEP 3116)

您的原始代码可以更改为:

proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
out = io.TextIOWrapper(proc.stdout, newline='')

for line in out:
    # line is delimited with the universal newline convention and actually contains
    #  the original end of line, be it a raw \r, \n of the pair \r\n
    ...