etc./StackOverFlow

바이트를 문자열로 변환

청렴결백한 만능 재주꾼 2021. 10. 27. 23:23
반응형

질문자 :Tomas Sedovic


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

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

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

 >>> 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'

그러나 출력을 일반 Python 문자열로 사용하고 싶습니다. 다음과 같이 인쇄할 수 있습니다.

 >>> 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'

바이트열 값을 문자열로 다시 변환하려면 어떻게 해야 합니까? 내 말은, 수동으로 수행하는 대신 "배터리"를 사용하는 것입니다. 그리고 Python 3에서 괜찮았으면 합니다.



문자열을 생성하려면 바이트열 객체를 디코딩해야 합니다.

 >>> b"abcde" b'abcde' # utf-8 is used here because it is a very common encoding, but you # need to use the encoding your data is actually in. >>> b"abcde".decode("utf-8") 'abcde'

Aaron Maenpaa

바이트 문자열을 디코딩하여 문자(유니코드) 문자열로 변환해야 합니다.

파이썬 2에서

 encoding = 'utf-8' 'hello'.decode(encoding)

또는

 unicode('hello', encoding)

파이썬 3에서

 encoding = 'utf-8' b'hello'.decode(encoding)

또는

 str(b'hello', encoding)

dF.

나는 이 방법이 쉽다고 생각한다.

 >>> bytes_data = [112, 52, 52] >>> "".join(map(chr, bytes_data)) 'p44'

Sisso

인코딩을 모르는 경우 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 에도 동일하게 적용됩니다 . 코드페이지 레이아웃 ordinal not in range 악명 높은 서수로 질식하는 부분을 참조하세요.

업데이트 20150604 : Python 3에는 데이터 손실 및 충돌 없이 바이너리 데이터로 인코딩하기 위한 surrogateescape 오류 전략이 있다는 소문이 있지만 두 성능을 모두 검증하려면 [binary] -> [str] -> [binary] 신뢰성.

업데이트 20170116 backslashreplace 오류 처리기를 사용하여 알 수 없는 모든 바이트를 슬래시 이스케이프할 수도 있습니다. 이는 Python 3에서만 작동하므로 이 해결 방법을 사용하더라도 여전히 다른 Python 버전에서 일관되지 않은 출력을 얻을 수 있습니다.

 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'))

자세한 내용은 Python의 유니코드 지원 을 참조하세요.

업데이트 20170119 : Python 2 및 Python 3 모두에서 작동하는 슬래시 이스케이프 디코딩을 구현하기로 결정했습니다. cp437 솔루션보다 느려야 하지만 모든 Python 버전에서 동일한 결과 를 생성해야 합니다.

 # --- 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'))

anatoly techtonik

Python 3 에서 기본 인코딩은 "utf-8" 이므로 다음을 직접 사용할 수 있습니다.

 b'hello'.decode()

에 해당하는

 b'hello'.decode(encoding="utf-8")

반면 에 Python 2 에서는 인코딩이 기본 문자열 인코딩으로 기본 설정됩니다. 따라서 다음을 사용해야 합니다.

 b'hello'.decode(encoding)

여기서 encoding 은 원하는 인코딩입니다.

참고: 키워드 인수에 대한 지원은 Python 2.7에 추가되었습니다.


lmiguelvargasf

나는 당신이 실제로 이것을 원한다고 생각합니다.

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

아론의 대답은 당신이 사용 인코딩 알아야합니다 것을 제외하고 정확했다. 그리고 Windows는 'windows-1252'를 사용한다고 생각합니다. 콘텐츠에 비정상적인(ASCII가 아닌) 문자가 있는 경우에만 문제가 될 수 있지만 차이가 있을 수 있습니다.

그런데,이 문제 않는다는 사실은 이유는 파이썬 바이너리와 텍스트 데이터에 대한 서로 다른 두 가지 유형을 사용하여 이동한다는 것입니다 : 당신이 그것을 말하지 않는 한 인코딩을 모르고 있기 때문에, 그들 사이에 마술 변환 할 수 없습니다! 당신이 알 수 있는 유일한 방법은 Windows 문서를 읽는 것입니다(또는 여기에서 읽으십시오).


mcherm

Universal_newlines를 True로 설정합니다. 즉,

 command_stdout = Popen(['ls', '-l'], stdout=PIPE, universal_newlines=True).communicate()[0]

ContextSwitch

바이트 시퀀스를 텍스트로 해석하려면 해당 문자 인코딩을 알아야 합니다.

 unicode_text = bytestring.decode(character_encoding)

예시:

 >>> b'\xc2\xb5'.decode('utf-8') 'µ'

ls 명령은 텍스트로 해석할 수 없는 출력을 생성할 수 있습니다. b'/' 및 0 b'\0' 제외한 모든 바이트 시퀀스일 수 있습니다.

 >>> open(bytes(range(0x100)).translate(None, b'\0/'), 'w').close()

utf-8 인코딩을 사용하여 이러한 바이트 수프를 디코딩하려고 하면 UnicodeDecodeError 합니다.

더 나빠질 수 있습니다. 잘못된 호환되지 않는 인코딩을 사용하면 디코딩이 자동으로 실패하고 mojibake가 생성될 수 있습니다.

 >>> '—'.encode('utf-8').decode('cp1252') '—'

데이터가 손상되었지만 프로그램은 오류가 발생했음을 인식하지 못합니다.

일반적으로 사용할 문자 인코딩은 바이트 시퀀스 자체에 포함되지 않습니다. 이 정보를 대역 외에서 전달해야 합니다. 일부 결과는 다른 것보다 가능성이 높으므로 문자 인코딩을 추측 chardet 모듈이 존재합니다. 단일 Python 스크립트는 다른 위치에서 여러 문자 인코딩을 사용할 수 있습니다.


ls 출력은 디코딩할 수 없는 파일 이름 os.fsdecode() 함수를 사용하여 Python 문자열로 변환할 수 있습니다( sys.getfilesystemencoding()surrogateescape 오류 처리기를 사용함):

 import os import subprocess output = os.fsdecode(subprocess.check_output('ls'))

원래 바이트를 얻으려면 os.fsencode() 사용할 수 있습니다.

universal_newlines=True 매개변수를 전달하면 subprocesslocale.getpreferredencoding(False) 을 사용하여 바이트를 디코딩합니다(예: Windows에서 cp1252

즉석에서, 바이트 스트림 디코딩하기 io.TextIOWrapper() : 사용될 수있는 .

다른 명령은 출력에 다른 문자 인코딩을 사용할 수 있습니다. 예를 들어 dir 내부 명령( cmd )은 cp437을 사용할 수 있습니다. 출력을 디코딩하려면 인코딩을 명시적으로 전달할 수 있습니다(Python 3.6+):

 output = subprocess.check_output('dir', shell=True, encoding='cp437')

os.listdir() (Windows Unicode API 사용)과 다를 수 있습니다. '\xb6' '\x14' 로 대체할 수 있습니다. — Python의 cp437 코덱은 U 대신 U+0014 문자를 제어하기 위해 b'\x14' +00B6(¶). 임의의 유니코드 문자가 있는 파일 이름을 지원하려면 ASCII가 아닌 유니코드 문자를 포함할 수 있는 PowerShell 출력을 Python 문자열로 디코딩을 참조하세요.


jfs

이 질문은 실제로 subprocess 출력에 대해 묻기 때문에 더 직접적인 접근 방식을 사용할 수 있습니다. 가장 현대적인 것은 subprocess.check_output 사용하고 text=True (Python 3.7+)를 전달하여 시스템 기본 코딩을 사용하여 stdout을 자동으로 디코딩하는 것입니다.

 text = subprocess.check_output(["ls", "-l"], text=True)

Python 3.6의 경우 Popen 은 인코딩 키워드를 허용합니다.

 >>> 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é'

wim

@Aaron Maenpaa의 답변 이 작동하는 동안 사용자는 최근에 다음과 같이 질문했습니다.

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

당신이 사용할 수있는:

 command_stdout.decode()

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

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


serv-inc

decode() 을 시도하여 다음을 얻어야 하는 경우:

AttributeError: 'str' 개체에 'decode' 속성이 없습니다.

캐스트에서 인코딩 유형을 직접 지정할 수도 있습니다.

 >>> my_byte_str b'Hello World' >>> str(my_byte_str, 'utf-8') 'Hello World'

Broper

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

 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

eafloresf

Windows 시스템의 데이터로 작업할 때( \r\n 줄 끝) 내 대답은 다음과 같습니다.

 String = Bytes.decode("utf-8").replace("\r\n", "\n")

왜요? 여러 줄 Input.txt로 이것을 시도하십시오.

 Bytes = open("Input.txt", "rb").read() String = Bytes.decode("utf-8") open("Output.txt", "w").write(String)

모든 줄 끝이 두 배가되어 ( \r\r\n ) 추가 빈 줄이 생깁니다. Python의 텍스트 읽기 함수는 일반적으로 문자열이 \n 만 사용하도록 줄 끝을 정규화합니다. Windows 시스템에서 이진 데이터를 수신하는 경우 Python은 이를 수행할 기회가 없습니다. 따라서,

 Bytes = open("Input.txt", "rb").read() String = Bytes.decode("utf-8").replace("\r\n", "\n") open("Output.txt", "w").write(String)

원본 파일을 복제합니다.


bers

byte 에서 string 로 변환하는 훨씬 더 안전하고 Pythonic 접근 방식입니다.

 def byte_to_str(bytes_or_str): if isinstance(bytes_or_str, bytes): # Check if it's 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

Inconnu

"셸 명령을 실행하고 출력을 바이트 대신 텍스트로 가져오기"의 특정 subprocess.run 을 사용하고 text=True 전달해야 합니다(출력을 캡처하려면 capture_output=True

 command_result = subprocess.run(["ls", "-l"], capture_output=True, text=True) command_result.stdout # is a `str` containing your program's stdout

text universal_newlines 라고 불리며 Python 3.7에서 변경되었습니다. 3.7 이전의 Python 버전을 지원하려면 text=True 대신 universal_newlines=True


Boris

sys에서 — 시스템별 매개변수 및 함수 :

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


Zhichang Yu

def toString(string): try: return v.decode("utf-8") except ValueError: return string b = b'97.080.500' s = '97.080.500' print(toString(b)) print(toString(s))

Leonardo Filipe

바이트로 변환된 문자열뿐만 아니라 모든 바이트를 변환하려면 다음을 수행하십시오.

 with open("bytesfile", "rb") as infile: str = base64.b85encode(imageFile.read()) with open("bytesfile", "rb") as infile: str2 = json.dumps(list(infile.read()))

그러나 이것은 매우 효율적이지 않습니다. 2MB 사진을 9MB로 변환합니다.


HCLivess

이 시도

 bytes.fromhex('c3a9').decode('utf-8')

Victor Choy

.decode() 디코딩하십시오. 그러면 문자열이 디코딩됩니다. 'utf-8' )을 전달합니다.


Aarav Dave

이것을 사용해보십시오. utf-8 과 같이 문자 집합이 아닌 모든 바이너리를 무시하고 깨끗한 문자열을 반환합니다. python3.6 이상에서 테스트되었습니다.

 def bin2str(text, encoding = 'utf-8'): """Converts a binary to Unicode string by removing all non Unicode char text: binary string to work on encoding: output encoding *utf-8""" return text.decode(encoding, 'ignore')

여기에서 함수는 바이너리를 가져와 디코딩합니다(파이썬 사전 정의된 문자 집합을 사용하여 바이너리 데이터를 문자로 변환하고 ignore 인수는 바이너리에서 문자 집합이 아닌 모든 데이터를 무시하고 마지막으로 원하는 string 값을 반환합니다.

인코딩이 확실하지 않은 경우 sys.getdefaultencoding() 을 사용하여 장치의 기본 인코딩을 가져옵니다.


Ratul Hasan

출처 : http:www.stackoverflow.com/questions/606191/convert-bytes-to-a-string

반응형