Como Converter Bytes em Strings em Python 2 e Python 3

  1. Converter Bytes para String em Python 2.x
  2. Converta Bytes para String em Python 3.x
  3. Comparação de performance e conclusão de diferentes métodos de conversão de bytes em string

Este artigo tutorial irá introduzir como converter bytes para string em Python 2.x e Python 3.x.

Converter Bytes para String em Python 2.x

em Python 2.7 é idêntica a str, portanto a variável iniciada como bytes é a string intrinsecamente.

Python 2.7.10 (default, May 23 2015, 09:44:00) [MSC v.1500 64 bit (AMD64)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> A = b'cd'
>>> A
'cd'
>>> type(A)
<type 'str'>

Converta Bytes para String em Python 3.x

bytes é um novo tipo de dado introduzido em Python 3.

Python 3.6.3 (v3.6.3:2c5fed8, Oct  3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> A = b'cd'
>>> A
b'cd'
>>> type(A)
<class 'bytes'>
>>> 

O tipo de dados dos elementos no bytes é int.

>>> A = b'cd'
>>> A[0]
99
>>> type(A[0])
<class 'int'>

Converta Bytes para String utilizando decode no Python 3.x

O método .decode de bytes poderia converter bytes para string com o método dado encoding. Está OK na maioria dos casos se você deixar o método encoding como padrão utf-8, mas nem sempre é seguro porque os bytes poderiam ser codificados com outro método de codificação ao invés de utf-8.

>>> b'\x50\x51'.decode()
'PQ'
>>> b'\x50\x51'.decode('utf-8')
'PQ'
>>> b'\x50\x51'.decode(encoding = 'utf-8')
'PQ'

As três maneiras de decodificar os bytes como mostrado acima são idênticas porque o utf-8 é utilizado como método de codificação.

Pode gerar erros quando o utf-8 é utilizado mas os bytes não são codificados com ele.

>>> b'\x50\x51\xffed'.decode('utf-8')
Traceback (most recent call last):
  File "<pyshell#16>", line 1, in <module>
    b'\x50\x51\xffed'.decode('utf-8')
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 2: invalid start byte

Nós obtemos o UnicodeDecodeError que diz que utf-8 não é o codec correto.

Temos duas abordagens para resolver este problema de encoding.

backslashreplace, ignore ou replace como parâmetros para errors

O decode tem o outro parâmetro além de encoding - errors. Ele define o comportamento quando um error acontece. O valor padrão de errors é strict, o que significa que ele levanta um erro se o erro acontecer no processo de decodificação.

O error tem outras opções como ignore, replace ou outros nomes registrados codecs.register_error, backslashreplace por exemplo.

O ignore ignora os erros de decodificação errados e cria a string de saída como pode.

O replace substitui os caracteres correspondentes pelos caracteres definidos no método encoding como dado.backslashreplace substitui os caracteres que não puderam ser decodificados com o mesmo conteúdo dos bytes originais.

>>> b'\x50\x51\xffed'.decode('utf-8', 'backslashreplace')
'PQ\\xffed'
>>> b'\x50\x51\xffed'.decode('utf-8', 'ignore')
'PQed'
>>> b'\x50\x51\xffed'.decode('utf-8', 'replace')
'PQ�ed'

MS-DOS cp437 codificação pode ser utilizada se a codificação dos dados dos bytes for desconhecida.

>>> b'\x50\x51\xffed'.decode('cp437')
'PQ\xa0ed'

chr para converter os bytes para string em Python 3.x

chr(i, /) retorna uma string Unicode de um caractere com ordinal. Ele poderia converter o elemento de bytes para um string mas não o completo bytes.

Poderíamos utilizar a compreensão de lista ou map para obter a string convertida de bytes enquanto empregamos chr para elemento individual.

>>> A =  b'\x50\x51\x52\x53'
>>> "".join([chr(_) for _ in A])
'PQRS'
>>> "".join(map(chr, A))
'PQRS'

Comparação de performance e conclusão de diferentes métodos de conversão de bytes em string

Utilizamos timeit para comparar o desempenho do método introduzido neste tutorial - decode e chr.

>>> import timeit
>>> timeit.timeit('b"\x50\x51\x52\x53".decode()', number=1000000)
0.1356779
>>> timeit.timeit('"".join(map(chr, b"\x50\x51\x52\x53"))', number=1000000)
0.8295201999999975
>>> timeit.timeit('"".join([chr(_) for _ in b"\x50\x51\x52\x53"])', number=1000000)
0.9530071000000362

Você poderia ver pelo tempo de performance mostrado acima, decode() é muito mais rápido e chr() é relativamente ineficiente porque precisa reconstruir a string a partir do caractere de string único.

Nós recomendamos utilizar decode na aplicação crítica em termos de performance.

Artigo relacionado - Python Bytes

  • Como Converter strings em Bytes em Python
  • Converter Int para Binário em Python
  • Artigo relacionado - Python Encoding-Decoding

  • Converter Int para Binário em Python
  • Artigo relacionado - Python String

  • Converter uma string em nome de variável em Python
  • Como verificar se uma string está vazia de uma forma pitónica