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?
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())
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()
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