Почему Popen.communicate() возвращает b'hi\n 'вместо' hi '?
Может кто-нибудь объяснить, почему результат, который я хочу, "привет", предшествует букве "b" и следует за новой линией?
Я использую Python 3.3
>>> import subprocess
>>> print(subprocess.Popen("echo hi", shell=True,
stdout=subprocess.PIPE).communicate()[0])
b'hi\n'
Этот дополнительный "b" не появляется, если я запускаю его с помощью python 2.7
Ответы
Ответ 1
Команда echo по умолчанию возвращает символ новой строки
Сравните с этим:
print(subprocess.Popen("echo -n hi", \
shell=True, stdout=subprocess.PIPE).communicate()[0])
Что касается b, предшествующего строке, это указывает, что это байтовая последовательность, которая эквивалентна нормальной строке в Python 2. 6+
http://docs.python.org/3/reference/lexical_analysis.html#literals
Ответ 2
b
указывает, что у вас есть bytes
, который представляет собой двоичную последовательность байтов, а не строку символов Unicode, Подпроцессы выводят байты, а не символы, так что возвращается communicate()
.
Тип bytes
не доступен непосредственно print()
, поэтому вам показывают repr
bytes
. Если вы знаете кодировку полученных вами байтов из подпроцесса, вы можете использовать decode()
для преобразования их в печатный str
:
>>> print(b'hi\n'.decode('ascii'))
hi
Конечно, этот конкретный пример работает только в том случае, если вы фактически получаете ASCII из подпроцесса. Если это не ASCII, вы получите исключение:
>>> print(b'\xff'.decode('ascii'))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 0…
Новая строка является частью вывода echo hi
. Задача echo
состоит в том, чтобы выводить параметры, которые вы передаете, а затем новую строку. Если вас не интересует пробел, окружающий вывод процесса, вы можете использовать strip()
так:
>>> b'hi\n'.strip()
b'hi'
Ответ 3
Как упоминалось ранее, echo hi
действительно возвращает hi\n
, что является ожидаемым поведением.
Но вы, вероятно, хотите просто получить данные в "правильном" формате и не иметь дело с кодировкой. Все, что вам нужно сделать, это передать universal_newlines=True
вариант для subprocess.Popen()
:
>>> import subprocess
>>> print(subprocess.Popen("echo hi",
shell=True,
stdout=subprocess.PIPE,
universal_newlines=True).communicate()[0])
hi
Таким образом, Popen()
заменит эти нежелательные символы сам по себе.
Ответ 4
b - это представление байтов, а \n - результат выхода эха.
Далее будут напечатаны только данные результата
import subprocess
print(subprocess.Popen("echo hi", shell=True,stdout=subprocess.PIPE).communicate()[0].decode('utf-8').strip())
Ответ 5
'#!/usr/bin/python3
import subprocess
nginx_ver = subprocess.getstatusoutput("nginx -v")
print(nginx_ver)'
Output: (0, 'nginx version: nginx/1.12.1')