Subprocess popen stdout

Я изучаю subprocess, но у меня есть небольшая путаница с этим кодом:

import subprocess

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

Вывод:

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'

Как вы можете видеть, выход формируется. Но я не знаю, почему в конце символ b'' и \n.

Если я запустил эту команду в моем терминале, то не эти char.

Нормальный выход:

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)

Как я могу удалить их?

Ответ 1

Вероятно, вы используете python3 - python изменил способ чтения/записи определенных объектов, и теперь существует реальный объект bytes(). Чтобы получить нужную строку, вам просто нужно:

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

Вам также может понадобиться снять новую строку (\n) с вашего вывода; Я не помню, как stdout выполняет буферизацию/отчетность:

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

Ответ 2

b'' - это текстовое представление для объектов bytes в Python 3.

Чтобы напечатать байты как есть, используйте двоичный поток - 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..

Чтобы получить вывод в виде текста (строка Юникода), вы можете использовать параметр universal_newlines=True:

#!/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) кодирование символов используется для декодирования вывода.

Если дочерний процесс использует другую кодировку, вы можете явно указать его с помощью 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..

Для кода Python 2 и ссылок на возможные проблемы см. Python: прочитайте потоковый ввод из subprocess.communicate()

Ответ 3

Я думаю, вы используете python 3:

b для байтов, и это указывает, что это байтовая последовательность, которая эквивалентна нормальной строке в Python 2.6 +

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