subprocess popen stdout

2019-08-09 19:10发布

问题:

I'm learning subprocess, but I have a little confusion with this code:

import subprocess

proc = subprocess.Popen('lspci', stdout=subprocess.PIPE)
for line in proc.stdout:
    print(line)

Output:

b'00:00.0 Host bridge: Intel Corporation Xeon E3-1200 v2/3rd Gen Core processor DRAM Controller (rev 09)\n'
b'00:02.0 VGA compatible controller: Intel Corporation Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller (rev 09)\n'

As you can see, the output is formated. But I dont know why there is the character b'' and the \n at the end.

If I run this command in my terminal, there aren't these char.

Normal output:

00:00.0 Host bridge: Intel Corporation Xeon E3-1200 v2/3rd Gen Core processor DRAM Controller (rev 09)
00:02.0 VGA compatible controller: Intel Corporation Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller (rev 09)

How could I remove them?

回答1:

You're probably using python3 - python changed up the way certain objects read/write data, and now there's a real bytes() object. To get the string you want, you just need:

print(line.decode("utf8")) ## or some encoding; that one should print anything though

You may also need to strip the newline (\n) from your output; I can't remember how stdout does the buffering/reporting:

print(line.decode("utf8").strip())


回答2:

b'' is a text representation for bytes objects in Python 3.

To print bytes as is, use a binary stream -- sys.stdout.buffer:

#!/usr/bin/env python3
import sys
from subprocess import Popen, PIPE

with Popen('lspci', stdout=PIPE, bufsize=1) as process:
    for line in process.stdout: # b'\n'-terminated lines
        sys.stdout.buffer.write(line)
        # do something with line here..

To get the output as text (Unicode string), you could use universal_newlines=True parameter:

#!/usr/bin/env python3
from subprocess import Popen, PIPE

with Popen('lspci', stdout=PIPE, bufsize=1, universal_newlines=True) as process:
    for line in process.stdout: # b'\n', b'\r\n', b'\r' are recognized as newline
        print(line, end='')
        # do something with line here..

locale.getpreferredencoding(False) character encoding is used to decode the output.

If the child process uses a different encoding, then you could specify it explicitly using io.TextIOWrapper():

#!/usr/bin/env python3
import io
from subprocess import Popen, PIPE

with Popen('lspci', stdout=PIPE, bufsize=1) as process:
    for line in io.TextIOWrapper(process.stdout, encoding='utf-8'):
        print(line, end='')
        # do something with line here..

For Python 2 code and links to possible issues, see Python: read streaming input from subprocess.communicate()



回答3:

I think you use python 3:

b is for Bytes, and it indicates that it is a byte sequence which is equivilent to a normal string in Python 2.6+

see https://docs.python.org/3/reference/lexical_analysis.html#literals