¿La mejor manera de convertir cadenas a bytes en Python 3?

Parece que hay dos formas diferentes de convertir una cadena a bytes, como se ve en las respuestas a TypeError: ‘str’ no admite la interfaz del búfer

¿Cuál de estos métodos sería mejor o más pythonico? ¿O es solo una cuestión de preferencia personal?

b = bytes(mystring, 'utf-8') b = mystring.encode('utf-8') 

Si miras los documentos en busca de bytes , te apunta a bytearray :

bytearray ([fuente [, encoding [, errores]]])

Devuelve una nueva matriz de bytes. El tipo de bytearray es una secuencia mutable de enteros en el rango 0 <= x <256. Tiene la mayoría de los métodos habituales de secuencias mutables, descritos en Tipos de secuencias mutables, así como la mayoría de los métodos que tiene el tipo de bytes, consulte Bytes y Métodos de matriz de bytes.

El parámetro fuente opcional se puede usar para inicializar la matriz de varias maneras diferentes:

Si es una cadena, también debe dar los parámetros de encoding (y, opcionalmente, errores); bytearray () luego convierte la cadena a bytes usando str.encode ().

Si es un entero, la matriz tendrá ese tamaño y se inicializará con bytes nulos.

Si es un objeto que se ajusta a la interfaz del búfer, se utilizará un búfer de solo lectura del objeto para inicializar la matriz de bytes.

Si es un iterable, debe ser un iterable de enteros en el rango 0 <= x <256, que se utilizan como el contenido inicial de la matriz.

Sin un argumento, se crea una matriz de tamaño 0.

Así que los bytes pueden hacer mucho más que simplemente codificar una cadena. Es Pythonic que le permitiría llamar al constructor con cualquier tipo de parámetro fuente que tenga sentido.

Para codificar una cadena, creo que some_string.encode(encoding) es más Pythonic que usar el constructor, porque es la que más se documenta a sí misma: “tomar esta cadena y codificarla con esta encoding” es más clara que los bytes(some_string, encoding) – no hay ningún verbo explícito cuando usas el constructor.

Edición: he comprobado la fuente de Python. Si pasa una cadena Unicode a bytes utilizando CPython, llama a PyUnicode_AsEncodedString , que es la implementación de la encode ; así que solo estás saltando un nivel de indirección si llamas a encode .

Además, vea el comentario de unicode_string.encode(encoding) : unicode_string.encode(encoding) también es más Pythonic porque su inverso es byte_string.decode(encoding) y la simetría es agradable.

Es más fácil de lo que se piensa:

 my_str = "hello world" my_str_as_bytes = str.encode(my_str) type(my_str_as_bytes) # ensure it is byte representation my_decoded_str = my_str_as_bytes.decode() type(my_decoded_str) # ensure it is string representation 

La mejor manera es ninguno de los dos, pero el tercero. El primer parámetro para encode defecto 'utf-8' desde Python 3.0. Así, la mejor manera es

 b = mystring.encode() 

Esto también será más rápido, porque el argumento predeterminado no se traduce en la cadena "utf-8" en el código C, sino en NULL , que es mucho más rápido de verificar.

Aquí hay algunos tiempos:

 In [1]: %timeit -r 10 'abc'.encode('utf-8') The slowest run took 38.07 times longer than the fastest. This could mean that an intermediate result is being cached. 10000000 loops, best of 10: 183 ns per loop In [2]: %timeit -r 10 'abc'.encode() The slowest run took 27.34 times longer than the fastest. This could mean that an intermediate result is being cached. 10000000 loops, best of 10: 137 ns per loop 

A pesar de la advertencia, los tiempos se mantuvieron estables después de repetidas ejecuciones: la desviación fue de apenas el 2%.


El uso de encode() sin un argumento no es compatible con Python 2, como en Python 2 la encoding de caracteres predeterminada es ASCII .

 >>> 'äöä'.encode() Traceback (most recent call last): File "", line 1, in  UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128) 

Simplemente puede convertir la cadena a bytes usando:

a_string.encode()

y simplemente puede convertir bytes a cadena usando:

some_bytes.decode()

bytes.decode y str.encode tienen encoding='utf-8' como valor predeterminado.

Las siguientes funciones (tomadas de Effective Python ) podrían ser útiles para convertir str en bytes y bytes en str :

 def to_bytes(bytes_or_str): if isinstance(bytes_or_str, str): value = bytes_or_str.encode() # uses 'utf-8' for encoding else: value = bytes_or_str return value # Instance of bytes def to_str(bytes_or_str): if isinstance(bytes_or_str, bytes): value = bytes_or_str.decode() # uses 'utf-8' for encoding else: value = bytes_or_str return value # Instance of str 
 so_string = 'stackoverflow' so_bytes = so_string.encode( )