如何正确读取子进程Popen的输出?

时间:2015-04-09 19:38:29

标签: python python-3.x subprocess

我正在尝试将stderr重定向到stdout并读取命令的输出。它看起来像代码工作,但当它到达输出的末尾时,它会抛出异常

代码:

with Popen(["bash", "-c", "for ((i=0;i<10;i++)); do echo $i; sleep .5; done"],
           stderr=subprocess.STDOUT) as proc:
    out, err = proc.communicate()
    for line in out:
        if line:
            print(line)

输出:

0
1
2
3
4
5
6
7
8
9
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-28-3c150d6a4092> in <module>()
      2            stderr=subprocess.STDOUT) as proc:
      3         out, err = proc.communicate()
----> 4         for line in out:
      5                 if line:
      6                         print(line)

TypeError: 'NoneType' object is not iterable

3 个答案:

答案 0 :(得分:1)

我知道,你可以用另一种方法实现你想要的东西,但我想解释你的第一个版本是多么令人满意。

问题是PIPE中没有输出任何proc,因此输出不会导致&#34;旅行&#34;通过你的脚本,它直接进入屏幕,这就是你看到输出的原因:

0
1
2
3
4
5
6
7
8
9

然后在行中:

out, err = proc.communicate() # out is None, since you don't 
                              # pass the argument "stdout=subprocess.PIPE"
                              # when creating proc.

以及稍后当您尝试迭代out时:

for line in out:  # TypeError: 'NoneType' object is not iterable
     ...          # We are talking about out variable here, which is None.
     print(line)  # This line never get hit.

解。

这里有一个小例子,将stdout重定向到stderr并使用communicate

import subprocess
import sys

proc = subprocess.Popen(['ls'], stderr=sys.stdout, shell=True) # Not the use of sys.stdout
out, err = proc.communicate()
print(err.decode("utf-8"))

答案 1 :(得分:0)

哦,看起来我需要设置stdout = PIPE,我不需要communicate()

with Popen(["bash", "-c", "for ((i=0;i<10;i++)); do echo $i; sleep .5; done"],
           stdout=subprocess.PIPE, stderr=subprocess.STDOUT) as proc:
    for line in proc.stdout:
        print(line.decode().rstrip())

使用J.F. Sebastian的universal_newlines提示:

with Popen(["bash", "-c", "for ((i=0;i<10;i++)); do echo $i; sleep .5; done"],
           stdout=subprocess.PIPE, 
           stderr=subprocess.STDOUT, 
           universal_newlines=True) as proc:
    for line in proc.stdout:
        print(line, end='')

答案 2 :(得分:0)

  

TypeError:&#39; NoneType&#39;对象不可迭代

您应添加stdout=PIPE否则.communicate() 始终会为None返回out

btw,如果您的代码使用stdout=PIPE, stderr=STDOUT,那么err 总是 Noneout包含合并的stdout / stderr作为单个字节字符串,即,for byte in out一次产生一个字节,行。

如果您设置stdout=PIPE, stderr=PIPE并致电.communicate(),则可以单独获取stdout / stderr。