python '\ x00 - 바이트를 문자열로 변환 하시겠습니까?





8 Answers

나는이 방법이 쉽다라고 생각한다 :

bytes = [112, 52, 52]
"".join(map(chr, bytes))
>> p44
파이썬 bytes to

이 코드를 사용하여 외부 프로그램에서 표준 출력을 얻습니다.

>>> from subprocess import *
>>> command_stdout = Popen(['ls', '-l'], stdout=PIPE).communicate()[0]

communicate () 메소드는 바이트 배열을 반환합니다.

>>> command_stdout
b'total 0\n-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file1\n-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file2\n'

그러나 출력을 일반적인 파이썬 문자열로 작업하고 싶습니다. 그래서 다음과 같이 인쇄 할 수 있습니다.

>>> print(command_stdout)
-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file1
-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file2

나는 binascii.b2a_qp() 메소드가 그것을위한 것이라고 생각했지만, 그것을 시도했을 때 같은 바이트 배열을 다시 얻었다 :

>>> binascii.b2a_qp(command_stdout)
b'total 0\n-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file1\n-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file2\n'

누구든지 바이트 값을 다시 문자열로 변환하는 방법을 알고 있습니까? 내 말은, 수동으로하는 대신 "배터리"를 사용하는 것입니다. 그리고 파이썬 3에서도 괜찮 으면 좋겠다.




인코딩을 모르는 경우 Python 3 및 Python 2 호환 방법으로 문자열에 이진 입력을 읽으려면 고대 MS-DOS cp437 인코딩을 사용하십시오.

PY3K = sys.version_info >= (3, 0)

lines = []
for line in stream:
    if not PY3K:
        lines.append(line)
    else:
        lines.append(line.decode('cp437'))

인코딩을 알 수 없으므로 영어 이외의 기호가 cp437 문자로 변환됩니다 (영어 문자는 대부분의 단일 바이트 인코딩 및 UTF-8과 일치하기 때문에 번역되지 않습니다).

UTF-8에 대한 임의의 바이너리 입력을 디코딩하는 것은 안전하지 않습니다.

>>> b'\x00\x01\xffsd'.decode('utf-8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 2: invalid
start byte

Python 2의 경우 인기가있는 latin-1 (기본값?)에도 동일하게 적용됩니다. Codepage Layout 의 누락 된 점을 참조하십시오. ordinal not in range 악명 높은 ordinal not in range 로 파이썬이 질식하는 곳입니다.

업데이트 20150604 : Python 3에는 데이터 손실 및 충돌없이 바이너리 데이터로 인코딩하는 surrogateescape 오류 전략이 있지만 성능 및 안정성을 검증하기 위해 [binary] -> [str] -> [binary] 변환 테스트가 필요하다는 소문이 있습니다.

업데이트 20170116 : Nearoo 님의 의견 감사 - backslashreplace 오류 처리기를 사용하여 알 수없는 모든 바이트를 backslashreplace 할 수 있습니다. 이것은 파이썬 3에서만 작동합니다. 따라서이 해결 방법을 사용하더라도 다른 파이썬 버전에서 일관성없는 결과를 얻을 수 있습니다 :

PY3K = sys.version_info >= (3, 0)

lines = []
for line in stream:
    if not PY3K:
        lines.append(line)
    else:
        lines.append(line.decode('utf-8', 'backslashreplace'))

자세한 내용은 https://docs.python.org/3/howto/unicode.html#python-s-unicode-support 를 참조하십시오.

업데이트 20170119 : 파이썬 2와 파이썬 3 모두에서 작동하는 슬래시 이스케이프 디코드를 구현하기로 결정했습니다. 더 느린 cp437 솔루션이어야하지만 모든 파이썬 버전에서 동일한 결과 가 생성되어야합니다.

# --- preparation

import codecs

def slashescape(err):
    """ codecs error handler. err is UnicodeDecode instance. return
    a tuple with a replacement for the unencodable part of the input
    and a position where encoding should continue"""
    #print err, dir(err), err.start, err.end, err.object[:err.start]
    thebyte = err.object[err.start:err.end]
    repl = u'\\x'+hex(ord(thebyte))[2:]
    return (repl, err.end)

codecs.register_error('slashescape', slashescape)

# --- processing

stream = [b'\x80abc']

lines = []
for line in stream:
    lines.append(line.decode('utf-8', 'slashescape'))



제 생각에 당신이 실제로 원하는 것은 이것입니다 :

>>> from subprocess import *
>>> command_stdout = Popen(['ls', '-l'], stdout=PIPE).communicate()[0]
>>> command_text = command_stdout.decode(encoding='windows-1252')

Aaron의 답변은 정확했지만 사용하는 데 필요한 인코딩을 알아야했습니다. 그리고 저는 Windows가 'windows-1252'를 사용한다고 생각합니다. 귀하의 콘텐츠에 비정상적인 (문자가 아닌) 문자가있는 경우에만 문제가됩니다. 그러나 차이가있을 것입니다.

그건 그렇고 사실은 파이썬이 바이너리와 텍스트 데이터를 위해 두 가지 다른 유형을 사용하도록 이동 한 이유입니다. 말하지 않으면 인코딩을 모르기 때문에 마술처럼 변환 할 수 없습니다! 당신이 아는 유일한 방법은 Windows 문서를 읽는 것입니다 (또는 여기에서 읽으십시오).




@Aaron Maenpaa의 답변 이 작동하는 동안 사용자가 최근에 물었습니다.

더 이상 간단한 방법이 있습니까? 'fhand.read (). decode ( "ASCII")'[...] 너무 길어!

당신이 사용할 수있는

command_stdout.decode()

decode() 에는 표준 인수가 있습니다.

codecs.decode(obj, encoding='utf-8', errors='strict')




이 질문은 실제로 subprocess 출력에 대해 묻기 때문에 Popen 은 (Python 3.6 이상에서) encoding 키워드를 허용하기 때문에보다 직접적인 접근 방식을 사용할 수 있습니다.

>>> from subprocess import Popen, PIPE
>>> text = Popen(['ls', '-l'], stdout=PIPE, encoding='utf-8').communicate()[0]
>>> type(text)
str
>>> print(text)
total 0
-rw-r--r-- 1 wim badger 0 May 31 12:45 some_file.txt

다른 사용자의 일반적인 대답은 바이트를 텍스트로 디코딩 하는 것입니다.

>>> b'abcde'.decode()
'abcde'

인수가 sys.getdefaultencoding() 이 사용됩니다. 데이터가 sys.getdefaultencoding() 이 아닌 경우 decode 호출에 명시 적으로 인코딩을 지정해야합니다.

>>> b'caf\xe9'.decode('cp1250')
'café'



목록 정리 기능을 만들었습니다.

def cleanLists(self, lista):
    lista = [x.strip() for x in lista]
    lista = [x.replace('\n', '') for x in lista]
    lista = [x.replace('\b', '') for x in lista]
    lista = [x.encode('utf8') for x in lista]
    lista = [x.decode('utf8') for x in lista]

    return lista



파이썬 3의 경우, 이것은 byte 에서 string 으로 변환하는 훨씬 더 안전하고 파이썬 적인 접근법입니다 :

def byte_to_str(bytes_or_str):
    if isinstance(bytes_or_str, bytes): #check if its in bytes
        print(bytes_or_str.decode('utf-8'))
    else:
        print("Object not of byte type")

byte_to_str(b'total 0\n-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file1\n-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file2\n')

산출:

total 0
-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file1
-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file2



http://docs.python.org/3/library/sys.html ,

표준 스트림에서 /로 이진 데이터를 쓰거나 읽으려면 기본 이진 버퍼를 사용하십시오. 예를 들어, stdout에 바이트를 쓰려면 sys.stdout.buffer.write (b'abc ')를 사용하십시오.




Related