Saltar al contenido principal

Cómo convertir bytes en cadenas en Python

Para convertir bytes en cadenas en Python, podemos utilizar el método .decode(), especificando la codificación adecuada.
Actualizado 30 jul 2024  · 8 min de lectura

Una de las secuencias incorporadas menos conocidas en Python es bytes, que es una secuencia inmutable de enteros. Cada número entero representa un byte de datos. Los datos suelen transmitirse a través de redes y programas en forma de bytes. Los bytes no son legibles por los humanos, y a menudo necesitamos convertirlos en cadenas en nuestros programas Python.

Este tutorial explora las técnicas de conversión de bytes a cadenas en Python. Si te interesa la operación inversa, consulta mi tutorial sobre cómo convertir cadenas en bytes en Python.

Empecemos con una respuesta breve para los que tengáis prisa.

Respuesta corta: Cómo convertir bytes en cadenas en Python

La principal herramienta para convertir bytes en cadenas en Python es el método .decode():

data = b"\xc3\xa9clair"
text = data.decode(encoding="utf-8")
print(text)
éclair

El método .decode() devuelve una cadena que representa el objeto bytes. En este ejemplo, se utiliza la descodificación UTF-8. UTF-8 es la codificación por defecto, por lo que no es necesaria en el ejemplo anterior, pero también podemos utilizar otras codificaciones.

Comprender los bytes y las cadenas en Python

Python tiene incorporada la estructura de datos bytes, que es una secuencia inmutable de enteros en el rango de 0 a 255. Un número entero dentro de este rango de 256 números puede representarse utilizando ocho bits de datos, lo que equivale a un byte. Por tanto, cada elemento de un objeto bytes es un número entero que representa un byte.

Utilicemos el constructor bytes() para crear un objeto bytes a partir de una lista:

data = bytes([68, 97, 116, 97, 67, 97, 109, 112])
print(type(data))
<class 'bytes'>

Esta secuencia de números enteros es inmutable:

data[0] = 100
Traceback (most recent call last):
 ...
   data[0] = 100
   ~~~~^^^
TypeError: 'bytes' object does not support item assignment

Python lanza un TypeError cuando intentamos cambiar un valor dentro de esta secuencia. Confirmemos que un objeto bytes sólo puede contener números enteros en el rango de 0 a 255:

data = bytes([254, 255, 256])
Traceback (most recent call last):
 ...
   data = bytes([254, 255, 256])
          ^^^^^^^^^^^^^^^^^^^^^^
ValueError: bytes must be in range(0, 256)

En ValueError se establece que un número entero que represente un byte debe ser miembro de range(0, 256). Se excluye el final del rango, como es la convención con un rango de números en Python.

Podemos visualizar el objeto bytes utilizando print():

data = bytes([68, 97, 116, 97, 67, 97, 109, 112])
print(data)
b'DataCamp'

La representación muestra el objeto bytes representado por caracteres. Python muestra los enteros utilizando los caracteres ASCII correspondientes a esos valores. El prefijo b delante de los caracteres entre comillas indica que se trata de un objeto bytes.

También podemos crear un objeto bytes utilizando directamente el literal bytes:

data = b"DataCamp"
print(data)
print(data[0])
b'DataCamp'
68

El objeto se muestra con caracteres, pero sus elementos son enteros.

Sin embargo, los objetos bytes sólo son legibles para el ser humano cuando se utilizan números enteros correspondientes a caracteres ASCII imprimibles. Como ASCII es una codificación de 7 bits, contiene 128 códigos, pero sólo 95 de estos caracteres ASCII son imprimibles.

Los números enteros entre 0 y 127 que no tienen un carácter ASCII imprimible y los enteros entre 128 y 255 se muestran como números hexadecimales:

data = bytes([0, 68, 97, 116, 97, 67, 97, 109, 112, 200])
print(data)
b'\x00DataCamp\xc8'

El primer entero de la lista es ahora 0, que no es un carácter imprimible en ASCII. El objeto bytes muestra este número entero como \x00, la representación hexadecimal de 0. El número entero final es 200, que está fuera del rango ASCII pero dentro del rango de números enteros que pueden utilizarse en bytes. Python muestra este número entero como \xc8, que es 200 en hexadecimal.

Las estructuras de datos bytes y cadenas comparten características comunes. Ambas son secuencias inmutables, pero bytes contiene números enteros, mientras que las cadenas contienen caracteres:

data = bytes([68, 97, 116, 97, 67, 97, 109, 112])
print(data[0])

​text = "DataCamp"
print(text[0])
68
D

Los bytes se utilizan para transferir datos a través de las redes y entre diferentes interfaces. La siguiente sección de este artículo explora cómo convertir bytes en cadenas.

Convertir bytes en cadenas: El método .decode() Método

Un objeto bytes en Python sólo es legible por humanos cuando contiene caracteres ASCII legibles. En la mayoría de las aplicaciones, estos caracteres no son suficientes. Podemos convertir un objeto bytes en una cadena utilizando el método .decode():

data = bytes([68, 97, 116, 97, 67, 97, 109, 112])
text = data.decode()

print(text)
print(type(text))
DataCamp
<class 'str'>

Sin embargo, existen diferentes codificaciones para convertir entre bytes y cadenas. Los números enteros del ejemplo anterior representan caracteres ASCII imprimibles. Sin embargo, la codificación por defecto que se utiliza cuando no se pasa ningún argumento a .decode() es UTF-8, no ASCII. UTF-8 es la codificación más utilizada para los caracteres Unicode.

Los 128 primeros códigos UTF-8 coinciden con los códigos ASCII, por lo que los datos del objeto bytes se descodifican a la cadena "DataCamp" en el ejemplo anterior.

Sin embargo, Unicode contiene casi 150.000 caracteres. UTF-8 codifica todos los caracteres no ASCII en Unicode utilizando dos o más bytes.

Vamos a crear un nuevo objeto bytes y a descodificarlo:

data = bytes([195, 169])
print(data)

text = data.decode()
print(text)
b'\xc3\xa9'
é

El objeto bytes contiene dos bytes: los enteros 195 y 169. Python muestra la representación hexadecimal de estos bytes. Sin embargo, .decode() devuelve una cadena descodificando el objeto bytes utilizando la codificación UTF-8. El par de bytes b'\xc3\xa9' representa la letra e con acento agudo, é.

El método .decode() toma un argumento opcional para especificar la codificación:

text = data.decode("utf-8")
print(text)
é

UTF-8 es la codificación por defecto, pero se pueden utilizar otras codificaciones. También podemos convertir una cadena en un objeto bytes utilizando el método de cadena .encode() con varias codificaciones:

text = "éclair"
data = text.encode("utf-8")
print(data)

data = text.encode("utf-16")
print(data)
b'\xc3\xa9clair'
b'\xff\xfe\xe9\x00c\x00l\x00a\x00i\x00r\x00'

La misma cadena se convierte en diferentes objetos bytes según la codificación de caracteres que utilicemos.

Errores de codificación

La elección de las codificaciones de caracteres puede dar lugar a errores si se utiliza una codificación diferente al convertir entre bytes y cadenas. Utilicemos el ejemplo con la cadena "éclair" codificada en bytes utilizando la codificación UTF-8:

text = "éclair"
data = text.encode("utf-8")
print(data)
b'\xc3\xa9clair'

Esta secuencia de bytes representa caracteres utilizando la codificación UTF-8. El método .decode() produce un error si utilizamos una codificación incorrecta:

text = data.decode("ascii")
print(text)
Traceback (most recent call last):
 ...
   text = data.decode("ascii")
          ^^^^^^^^^^^^^^^^^^^^
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)

Sin embargo, podemos incluir el argumento opcional errors para gestionar cualquier error. El valor por defecto del parámetro errors es "strict", que genera un error por caracteres no válidos.

Se puede llamar al método .decode() con errors="ignore" para ignorar todos los caracteres no válidos:

text = data.decode("ascii", errors="ignore")
print(text)
clair

El primer carácter de la cadena original es é, que no es un carácter ASCII. Por tanto, .decode() devuelve una cadena sin el primer carácter.

Otra opción es llamar a .decode() con errors="replace", que sustituye los bytes no válidos por �:

text = data.decode("ascii", errors="replace")
print(text)
��clair

Esta salida muestra que faltan caracteres en la cadena. La elección del tratamiento de errores depende de la aplicación.

Convertir bytes en cadenas con str()

El método .decode() es la vía principal para convertir bytes en cadenas. Sin embargo, también es posible utilizar directamente el constructor str(). Si utilizas el constructor str() en un objeto bytes, se creará una representación en forma de cadena de los bytes sin procesar:

data = b'\xc3\xa9clair'
text = str(data)

print(text)
print(type(text))
b'\xc3\xa9clair'
<class 'str'>

Sin embargo, el constructor str() también acepta un argumento encoding, que podemos utilizar para crear una cadena basada en una codificación específica:

text = str(data, encoding='utf-8')
print(text)
éclair

Convertir bytes en cadenas con codecs.decode()

El módulo codecs de la biblioteca estándar de Python proporciona la interfaz para codificar y descodificar datos. Este módulo también proporciona una función .decode() que puede utilizarse para convertir bytes de Python en cadenas:

import codecs

​data = b'\xc3\xa9clair'
text = codecs.decode(data, encoding='utf-8')
print(text)
éclair

Estas técnicas de conversión alternativas no son métodos del tipo bytes, sino funciones que requieren que se pase el objeto bytes como argumento.

Conclusión

Los datos se transfieren a menudo como bytes, y muchas aplicaciones Python necesitan convertir entre bytes y cadenas. Un objeto bytes es una secuencia inmutable de bytes que puede convertirse a string utilizando una de las diversas codificaciones de caracteres.

La vía principal para convertir bytes de Python en una cadena es el método .decode(), que permite a los usuarios elegir una codificación y una estrategia de tratamiento de errores.

Puedes continuar tu aprendizaje de Python con los siguientes tutoriales y cursos:

Temas

Aprende Python con estos cursos

Certificación disponible

curso

Introducción a Python

4 hr
5.6M
Domina los fundamentos del análisis de datos con Python en sólo cuatro horas. Este curso online introducirá la interfaz de Python y explorará paquetes populares.
Ver detallesRight Arrow
Comienza El Curso
Ver másRight Arrow