Popen.communicate ()가 'hi'대신 b'hi \ n '을 반환하는 이유는 무엇입니까?


92

누군가 내가 원하는 결과 "hi"앞에 문자 'b'가 있고 뒤에 개행 문자가 오는 이유를 설명 할 수 있습니까?

내가 사용하고 파이썬 3.3

>>> import subprocess
>>> print(subprocess.Popen("echo hi", shell=True,
                           stdout=subprocess.PIPE).communicate()[0])
b'hi\n'

이 추가 'b'는 파이썬 2.7로 실행하면 나타나지 않습니다.


1
어떤 버전의 Python을 사용하고 있습니까?
Necrolyte2 2013 년

2
'b'에 대해서는 확실하지 않지만 개행 문자는 echo hiprints 때문 hi\r\n입니다. 이를 방지하기 위해 끝에 .strip () 또는 유사한 수정을 추가 할 수 있습니다.
azhrei

7
여기 check_output()대신 사용할 수 있습니다 .communicate().print(subprocess.check_output("echo hi", shell=True, universal_newlines=True), end="")
jfs

답변:



94

b당신이해야하는 것을 나타냅니다 bytes바이트의 바이너리 순서가 아니라 유니 코드 문자의 문자열이다. 문자가 아닌 출력 바이트를 하위 처리하므로 이것이 communicate()반환됩니다.

bytes유형은 직접하지 않습니다 print()당신이 표시되는 것, 그래서 수 reprbytes당신이 가지고 있습니다. 하위 프로세스에서받은 바이트의 인코딩을 알고있는 경우을 사용 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'

1
앞에 'b'없이 바이트 문자열을 인쇄하기 위해 print () 함수를 어떻게 얻습니까? 아니면 먼저 유니 코드 문자열로 변환해야합니까?
imagineerThat

os.popen텍스트 문자열을 반환 할 때 subprocess.Popen바이트 문자열 대신 반환 하는 방법이 있는지 궁금 합니다 .
Pavel Šimerda

11
나는 스스로 대답 할 것이다 universal_newlines. Popen객체가 텍스트 문자열을 받아들이고 반환하도록 하는 비밀 이름을 가진 옵션이있다 .
Pavel Šimerda

3
@ PavelŠimerda os.popen이 텍스트 문자열을 반환하는 동안, 적어도 Windows에서는 비 ASCII 문자에 대해 잘못 디코딩되고있는 것 같습니다. 예를 들어 check_output("dir"), 파일 이름 open에 독일어 움라우트가 포함되어 있으면를 실행 하고 출력에서 ​​파일 이름을 추출한 다음로 액세스하려고 하면 실패합니다. 버그 일 수 있습니다.
kdb

57

앞서 언급했듯이 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()이러한 원치 않는 기호가 그 자체로 대체됩니다.


11
universal_newlines=True매력처럼 작동했습니다. 이것은 ... 내 소견에서, 허용 대답해야한다
에단 스트라이더

3
여분의 빈 줄이 생성됩니다.
LoMaPh

1
종료 줄 바꿈을 자르려면 결과 문자열에 in (제거하기 위해 )과 a 가 모두 필요할 수 있습니다 . universal_newlines=TruePopenb''strip()
arielf

참고로 문서에 따르면 universal_newlines이제 text매개 변수에 대한 이전 버전과 호환되는 별칭 이며 더 명확하지만 Python 3.7 이상에서만 가능합니다.
Harry Cutts

작동하지 않기 때문에 여분의 빈 줄이 생성됩니다. universal_newlines는 제거하지 않습니다. \ n
kol23

8

b는 바이트 표현이고 \ n은 에코 출력의 결과입니다.

다음은 결과 데이터 만 인쇄합니다.

import subprocess
print(subprocess.Popen("echo hi", shell=True,stdout=subprocess.PIPE).communicate()[0].decode('utf-8').strip())
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.