Convertir bytes a cadena en Python

En este tutorial, repasaremos ejemplos de cómo convertir bytes en una cadena en Python 2 y 3. Usaremos la función decode(), la función str() y el módulo de códecs.

Introducción

En este artículo, veremos cómo convertir bytes a una cadena en Python. Al final de este artículo, tendrá una idea clara de qué son estos tipos y cómo manejar los datos de manera efectiva al usarlos.

Dependiendo de la versión de Python que esté usando, esta tarea será diferente. Aunque Python 2 ha llegado al final de su vida útil, muchos proyectos aún lo usan, por lo que incluiremos los enfoques de Python 2 y Python 3.

Convertir bytes en cadena en Python 3

Desde Python 3, la antigua forma ASCII de hacer las cosas tuvo que desaparecer, y Python se convirtió completamente en Unicode.

Esto significa que perdimos el tipo Unicode explícito: u"cadena" - ¡cada cadena es una u"cadena"!

Para diferenciar estas cadenas de cadenas de bytes buenas y antiguas, se nos presenta un nuevo especificador para ellas: la b"cadena".

Esto se agregó en Python 2.6, pero no tuvo otro propósito real que el de prepararse para Python 3, ya que todas las cadenas eran cadenas de bytes en 2.6.

Las cadenas de bytes en Python 3 se llaman oficialmente bytes, una secuencia inmutable de números enteros en el rango 0 <= x < 256. Otro objeto similar a bytes agregado en 2.6 es bytearray - similar a bytes, pero mutable.

Convertir bytes en cadenas con decode()

Echemos un vistazo a cómo podemos convertir bytes en una cadena, usando el método integrado decode() para la clase bytes:

1
2
3
4
5
6
7
8
9
>>> b = b"Lets grab a \xf0\x9f\x8d\x95!"
# Let's check the type
>>> type(b)
<class 'bytes'>

# Now, let's decode/convert them into a string
>>> s = b.decode('UTF-8')
>>> s
"Let's grab a 🍕!"

Al pasar el formato de codificación, decodificamos el objeto bytes en una cadena y lo imprimimos.

Convertir bytes en cadenas con códecs

Alternativamente, también podemos usar el módulo integrado codecs para este propósito:

1
2
3
4
5
>>> import codecs
>>> b = b'Lets grab a \xf0\x9f\x8d\x95!'

>>> codecs.decode(b, 'UTF-8')
"Let's grab a 🍕!"

Sin embargo, realmente no necesita pasar el parámetro de codificación, se recomienda pasarlo:

1
2
>>> codecs.decode(b)
"Let's grab a 🍕!"

Convertir bytes en cadenas con str()

Finalmente, puedes usar la función str(), que acepta varios valores y los convierte en cadenas:

1
2
3
>>> b = b'Lets grab a \xf0\x9f\x8d\x95!'
>>> str(b, 'UTF-8')
"Let's grab a 🍕!"

Sin embargo, asegúrese de proporcionar el argumento de codificación a str(); de lo contrario, podría obtener algunos resultados inesperados:

1
2
>>> str(b)
b'Lets grab a \xf0\x9f\x8d\x95!'

Esto nos lleva a las codificaciones una vez más. Si especifica la codificación incorrecta, el mejor de los casos es que su programa se bloquee porque no puede decodificar los datos. Por ejemplo, si intentáramos usar la función str() con UTF-16, recibiríamos lo siguiente:

1
2
>>> str(b, 'UTF-16')
'敌❴\u2073牧扡愠\uf020趟↕'

Esto es aún más importante dado que a Python 3 le gusta asumir Unicode, por lo que si está trabajando con archivos o fuentes de datos que usan una codificación oscura, asegúrese de prestar especial atención.

Convertir bytes en cadena en Python 2

En Python 2, un paquete de bytes y una cadena son prácticamente lo mismo: las cadenas son objetos que consisten en caracteres de 1 byte de longitud, lo que significa que cada carácter puede almacenar 256 valores. Es por eso que a veces se les llama cadenas de bytes.

Esto es excelente cuando se trabaja con datos de bytes: simplemente los cargamos en una variable y estamos listos para imprimir:

1
2
3
4
5
6
7
>>> s = "Hello world!"

>>> s
'Hello world!'

>>> len(s)
12

Sin embargo, el uso de caracteres Unicode en cadenas de bytes cambia un poco este comportamiento:

1
2
3
4
5
6
7
8
9
>>> s = "Let's grab a 🍕!"

>>> s
'Lets grab a \xf0\x9f\x8d\x95!'
# Where has the pizza gone to?

>>> len(s)
17
# Shouldn't that be 15?

Convertir bytes a Unicode (Python 2)

Aquí, tendremos que usar el tipo Unicode de Python 2, que se asume y se usa automáticamente en Python 3. Esto almacena cadenas como una serie de puntos de código, en lugar de bytes.

\xf0\x9f\x8d\x95 representa los bytes como números hexadecimales de dos dígitos, ya que Python no sabe cómo representarlos como caracteres ASCII:

1
2
3
4
5
6
7
8
9
>>> u = u"Let's grab a 🍕!"
u"Let's grab a \U0001f355!""

>>> u
"Let's grab a 🍕!"
# Yum.

>>> len(u)
15

Como puede ver arriba, la cadena Unicode contiene \U0001f355 - ¡un carácter de escape Unicode que nuestro terminal ahora sabe cómo imprimir como una rebanada de pizza! Establecer esto fue tan fácil como usar el especificador u antes del valor de la cadena de bytes.

Entonces, ¿cómo cambio entre los dos?

Puede obtener la cadena Unicode decodificando su cadena de bytes. Esto se puede hacer construyendo un objeto Unicode, proporcionando la cadena de bytes y una cadena que contenga el nombre de codificación como argumentos o llamando a .decode(encoding) en una cadena de bytes.

Convertir bytes en cadenas usando decode() (Python 2)

También puede usar codecs.encode(s, encoding) del módulo codecs.

1
2
3
4
5
6
7
8
>>> s = "Let's grab a \xf0\x9f\x8d\x95!"
>>> u = unicode(s, 'UTF-8')

>>> u
"Let's grab a 🍕!"

>>> s.decode('UTF-8')
"Let's grab a 🍕!"

Convertir bytes en cadenas usando códecs (Python 2)

O, usando el módulo codecs:

1
2
3
4
import codecs

>>> codecs.decode(s, 'UTF-8')
"Let's grab a 🍕!"

Sea consciente de su codificación

Una palabra de precaución aquí: los bytes se pueden interpretar de manera diferente en diferentes codificaciones. Con alrededor de 80 codificaciones diferentes disponibles listas para usar, puede que no sea fácil saber si tiene la correcta.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
s = '\xf8\xe7'

# This one will let us know we used the wrong encoding

>>> s.decode('UTF-8')
UnicodeDecodeError: 'utf8' codec can't decode byte 0xf8 in position 0:
invalid start byte

# These two overlaps and this is a valid string in both

>>> s.decode('latin1')
øç

s.decode('iso8859_5')
јч

El mensaje original era øç o јч, y ambos parecen ser conversiones válidas.

Conclusión

Como programadores, hay algunas cosas en las que debemos pensar constantemente y prepararnos activamente para evitar trampas. Esto es especialmente cierto en los niveles inferiores, donde rara vez vamos cuando usamos un lenguaje de alto nivel como Python como nuestro controlador diario.

Cosas como charsets, encodings y ​​binary están ahí para recordarnos que nuestro trabajo es codificar: codificar nuestros pensamientos en soluciones que funcionen. Afortunadamente, mucho de este pensamiento se convierte en parte de nuestra rutina después de algunas rondas en el teclado.

En este artículo, hemos repasado cómo convertir bytes a cadenas en Python.

Licensed under CC BY-NC-SA 4.0