¿Qué hace el carácter 'b' delante de un literal de cadena?

832

Aparentemente, la siguiente es la sintaxis válida:

my_string = b'The string'

Me gustaría saber:

  1. ¿Qué significa este bpersonaje delante de la cadena?
  2. ¿Cuáles son los efectos de usarlo?
  3. ¿Cuáles son las situaciones apropiadas para usarlo?

Encontré una pregunta relacionada aquí en SO, pero esa pregunta es sobre PHP y dice que bse usa para indicar que la cadena es binaria, a diferencia de Unicode, que era necesaria para que el código fuera compatible con la versión de PHP <6 , al migrar a PHP 6. No creo que esto se aplique a Python.

Encontré esta documentación en el sitio de Python sobre el uso de un ucarácter en la misma sintaxis para especificar una cadena como Unicode. Desafortunadamente, no menciona el carácter b en ninguna parte de ese documento.

Además, solo por curiosidad, ¿hay más símbolos que el by uque hacen otras cosas?

Jesse Webb
fuente

Respuestas:

417

Para citar la documentación de Python 2.x :

Un prefijo de 'b' o 'B' se ignora en Python 2; indica que el literal debería convertirse en un literal de bytes en Python 3 (por ejemplo, cuando el código se convierte automáticamente con 2to3). Un prefijo 'u' o 'b' puede ir seguido de un prefijo 'r'.

La documentación de Python 3 dice:

Los literales de bytes siempre tienen el prefijo 'b' o 'B'; producen una instancia del tipo de bytes en lugar del tipo str. Solo pueden contener caracteres ASCII; Los bytes con un valor numérico de 128 o superior deben expresarse con escapes.

NPE
fuente
44
Por lo tanto, parece que Python <v3 ignorará este carácter adicional. ¿Cuál sería un caso en v3 donde necesitaría usar una cadena ab en lugar de solo una cadena normal?
Jesse Webb
55
@Gweebz: si en realidad está escribiendo una cadena en una codificación particular en lugar de con escapes unicode (por ejemplo, b '\ xff \ xfe \ xe12' en lugar de '\ u32e1').
detly
77
En realidad, si ha importado unicode_literalsdesde __future__, esto "revertirá" el comportamiento de esta cadena en particular (en Python 2.x)
Romuald Brunet
34
Un poco más de narrativa en lenguaje sencillo alrededor de la documentación citada haría que esta sea una mejor respuesta en mi humilde opinión
Hack-R
2
De lo contrario, es una respuesta para alguien que ya lo entiende.
Rafael Eyng
681

Python 3.x hace una clara distinción entre los tipos:

  • str= '...'literales = una secuencia de caracteres Unicode (UTF-16 o UTF-32, dependiendo de cómo se compiló Python)
  • bytes= b'...'literales = una secuencia de octetos (enteros entre 0 y 255)

Si está familiarizado con Java o C #, piense en stras Stringy bytesas byte[]. Si está familiarizado con SQL, piense en stras NVARCHARy bytesas BINARYor BLOB. Si está familiarizado con el registro de Windows, piense strcomo REG_SZy bytescomo REG_BINARY. Si estás familiarizado con C (++), entonces olvida todo lo que has aprendido chary las cadenas, porque UN CARÁCTER NO ES UN BYTE . Esa idea es obsoleta desde hace mucho tiempo.

Usas strcuando quieres representar texto.

print('שלום עולם')

Se usa bytescuando desea representar datos binarios de bajo nivel como estructuras.

NaN = struct.unpack('>d', b'\xff\xf8\x00\x00\x00\x00\x00\x00')[0]

Puede codificar a stra un bytesobjeto.

>>> '\uFEFF'.encode('UTF-8')
b'\xef\xbb\xbf'

Y puedes decodificar a bytesen a str.

>>> b'\xE2\x82\xAC'.decode('UTF-8')
'€'

Pero no puedes mezclar libremente los dos tipos.

>>> b'\xEF\xBB\xBF' + 'Text with a UTF-8 BOM'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't concat bytes to str

La b'...'notación es algo confusa ya que permite que los bytes 0x01-0x7F se especifiquen con caracteres ASCII en lugar de números hexadecimales.

>>> b'A' == b'\x41'
True

Pero debo enfatizar, un personaje no es un byte .

>>> 'A' == b'A'
False

En Python 2.x

Las versiones anteriores a 3.0 de Python carecían de este tipo de distinción entre texto y datos binarios. En cambio, había:

  • unicode= u'...'literales = secuencia de caracteres Unicode = 3.xstr
  • str= '...'literales = secuencias de bytes / caracteres confundidos
    • Por lo general, texto codificado en alguna codificación no especificada.
    • Pero también se usa para representar datos binarios como struct.packsalida.

Para facilitar la transición de 2.x a 3.x, la b'...'sintaxis literal se hizo retroceder a Python 2.6, para permitir distinguir cadenas binarias (que deberían estar bytesen 3.x) de cadenas de texto (que deberían estar stren 3 .X). El bprefijo no hace nada en 2.x, pero le dice al 2to3script que no lo convierta a una cadena Unicode en 3.x.

Entonces sí, los b'...'literales en Python tienen el mismo propósito que en PHP.

Además, solo por curiosidad, ¿hay más símbolos que el byu que hacen otras cosas?

El rprefijo crea una cadena sin formato (p. Ej., r'\t'Es una barra invertida + en tlugar de una pestaña), y las comillas triples '''...'''o """..."""permiten literales de cadena de varias líneas.

dan04
fuente
2
¡Gracias! Lo entendí después de leer estas oraciones: "Para facilitar la transición de 2.x a 3.x, la sintaxis literal b '...' se convirtió en Python 2.6, para permitir distinguir cadenas binarias (que deberían ser bytes en 3.x) de cadenas de texto (que deberían ser str en 3.x). El prefijo b no hace nada en 2.x, pero le dice al script 2to3 que no lo convierta en una cadena Unicode en 3.x. "
tommy.carstensen
44
El 'A' == b'A' --> Falsecheque realmente lo deja claro. El resto es excelente, pero hasta ese momento no había entendido correctamente que una cadena de bytes no
Comodín el
12
'שלום עולם' == 'hello world'
Eli
13
Esto es mucho más claro que la respuesta aceptada que solo cita la documentación. La documentación para mí no tenía sentido, por lo que proporcionar más contexto en la documentación es increíble. ¡Gracias!
rayryeng 05 de
3
b "alguna cadena" .decode ('UTF-8'), creo que esa es la línea que muchos buscan
Marvin Thobejane
23

La b denota una cadena de bytes.

Los bytes son los datos reales. Las cadenas son una abstracción.

Si tuviera un objeto de cadena de caracteres múltiples y tomó un solo carácter, sería una cadena y podría tener más de 1 byte de tamaño dependiendo de la codificación.

Si toma 1 byte con una cadena de bytes, obtendría un solo valor de 8 bits de 0-255 y podría no representar un carácter completo si esos caracteres debido a la codificación eran> 1 byte.

TBH Usaría cadenas a menos que tuviera alguna razón específica de bajo nivel para usar bytes.


fuente
16

Desde el lado del servidor, si enviamos alguna respuesta, se enviará en forma de tipo de byte, por lo que aparecerá en el cliente como b'Response from server'

Para deshacerse de b'....'simplemente use el siguiente código:

Archivo del servidor:

stri="Response from server"    
c.send(stri.encode())

Archivo de cliente:

print(s.recv(1024).decode())

entonces imprimirá Response from server

Nani Chintha
fuente
1
¡No explica la pregunta que Jesse Webb ha hecho!
Chandra Kanth
Estaba diciendo que sin usar los métodos de codificación y decodificación, la salida de la cadena tendrá el prefijo b '', ya que Python lo toma como un tipo de byte en lugar de un tipo de cadena. 'usa lo anterior, eso es todo. ¿Qué no entendiste?
Nani Chintha
En realidad, esta es exactamente la respuesta al título de la pregunta que se hizo: P: "¿Qué hace b'x '?" R: "Hace 'x'.encode ()" Eso es literalmente lo que hace. El resto de la pregunta quería saber mucho más que esto, pero el título está respondido.
Michael Erickson
10

Aquí hay un ejemplo donde la ausencia de barrojaría una TypeErrorexcepción en Python 3.x

>>> f=open("new", "wb")
>>> f.write("Hello Python!")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' does not support the buffer interface

Agregar un bprefijo solucionaría el problema.

usuario3053230
fuente
9

Lo convierte en un bytesliteral (o stren 2.x), y es válido para 2.6+.

El rprefijo hace que las barras invertidas sean "no interpretadas" (no se ignoran, y la diferencia importa).

Ignacio Vazquez-Abrams
fuente
Esto suena mal de acuerdo con la documentación citada en la respuesta de aix; la b será ignorada en la versión de Python que no sea la 3.
Jesse Webb
2
Será un str2.x de cualquier manera, por lo que se podría decir que se ignora. La distinción es importante cuando importa unicode_literalsdesde el __future__módulo.
Ignacio Vazquez-Abrams
6

Además de lo que otros han dicho, tenga en cuenta que un solo carácter en Unicode puede constar de múltiples bytes .

La forma en que funciona Unicode es que tomó el antiguo formato ASCII (código de 7 bits que se parece a 0xxx xxxx) y agregó secuencias de múltiples bytes donde todos los bytes comienzan con 1 (1xxx xxxx) para representar caracteres más allá de ASCII para que Unicode esté al revés -compatible con ASCII.

>>> len('Öl')  # German word for 'oil' with 2 characters
2
>>> 'Öl'.encode('UTF-8')  # convert str to bytes 
b'\xc3\x96l'
>>> len('Öl'.encode('UTF-8'))  # 3 bytes encode 2 characters !
3
xjcl
fuente
2

Puedes usar JSON para convertirlo a diccionario

import json
data = b'{"key":"value"}'
print(json.loads(data))

{"valor clave"}


MATRAZ:

Este es un ejemplo de matraz. Ejecute esto en la línea de terminal:

import requests
requests.post(url='http://localhost(example)/',json={'key':'value'})

En matraz / routes.py

@app.route('/', methods=['POST'])
def api_script_add():
    print(request.data) # --> b'{"hi":"Hello"}'
    print(json.loads(request.data))
return json.loads(request.data)

{'valor clave'}

Karam Qusai
fuente