python子进程proc.stderr.read()引入额外的行?

use*_*012 5 python subprocess

我想运行一些命令并抓取输出到stderr的任何内容.我有两个版本的功能,执行此版本1.

def Getstatusoutput(cmd):
    """Return (status, output) of executing cmd in a shell."""

    import sys
    mswindows = (sys.platform == "win32")

    import os
    if not mswindows:
        cmd = '{ ' + cmd + '; }'

    pipe = os.popen(cmd + ' 2>&1', 'r')
    text = pipe.read()
    sts = pipe.close()
    if sts is None: sts = 0
    if text[-1:] == '\n': text = text[:-1]
    return sts, text  
Run Code Online (Sandbox Code Playgroud)

和版本2

def Getstatusoutput2(cmd):
    proc = subprocess.Popen(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
    return_code = proc.wait()
    return return_code, proc.stdout.read(), proc.stderr.read()
Run Code Online (Sandbox Code Playgroud)

第一个版本按照我的预期打印stderr输出.第二个版本在每行后打印一个空行.我怀疑这是由于版本1中的文本[-1:]行...但我似乎无法在第二版中做类似的事情.任何人都可以解释我需要做什么才能使第二个函数生成与第一个函数相同的输出而在它们之间没有额外的行(并且在最后)?

更新:这是我打印输出的方式这就是我打印的方式

      status, output, error = Getstatusoutput2(cmd)
      s, oldOutput = Getstatusoutput(cmd)
      print "oldOutput = <<%s>>" % (oldOutput)
      print "error = <<%s>>" % (error)
Run Code Online (Sandbox Code Playgroud)

jfs*_*jfs 2

您可以用来subprocess.check_output([cmd], stderr=STDOUT)捕获所有输出。

要单独捕获 stdout、stderr,您可以使用.communicate()

stdout, stderr = Popen([cmd], stdout=PIPE, stderr=PIPE).communicate()
Run Code Online (Sandbox Code Playgroud)

要获取末尾没有换行符的所有行,您可以调用stderr.splitlines().

为了避免打印额外的换行符(如果已经存在),请','在打印语句中的变量后面添加:

print line,
Run Code Online (Sandbox Code Playgroud)

或者如果您使用print()函数:

print(line, end='')
Run Code Online (Sandbox Code Playgroud)

笔记

Getstatusoutput2()如果产生足够的输出,您将阻塞cmd,请改用上述解决方案:

>>> len(Getstatusoutput2(['python', '-c',"""print "*"*2**6"""])[1])
65
>>> len(Getstatusoutput2(['python', '-c',"""print "*"*2**16"""])[1])
Run Code Online (Sandbox Code Playgroud)

Popen.wait()文档

等待子进程终止。设置并返回 returncode 属性。

警告:当使用 stdout=PIPE 和/或 stderr=PIPE 时,这会死锁,并且子进程会生成足够的输出到管道,从而阻止等待操作系统管道缓冲区接受更多数据。使用communicate()来避免这种情况。

相关使用communicate()而不是stdin.write()、stdout.read()或stderr.read()