top surveys stackoverflow programming popular most languages development python string bytestring

surveys - ¿Qué es un bytestring de Python?



stackoverflow surveys (4)

¿Qué es un bytestring de Python?

Todo lo que puedo encontrar son temas sobre cómo codificar para realizar pruebas o decodificar para ascii o utf-8 . Estoy tratando de entender cómo funciona bajo el capó. En una cadena ASCII normal, es una matriz o lista de caracteres, y cada carácter representa un valor ASCII de 0 a 255, por lo que es así como se sabe qué carácter está representado por el número. En Unicode, es la representación de 8 o 16 bytes para el carácter que le dice qué carácter es.

Entonces, ¿qué es un bytestring? ¿Cómo sabe Python qué personajes representar como qué? ¿Cómo funciona bajo el capó? Ya que puedes imprimir o incluso devolver estas cadenas y te muestra la representación de la cadena, no lo entiendo ...

Ok, entonces mi punto definitivamente se está perdiendo aquí. Me han dicho que es una secuencia de bytes inmutable sin ninguna interpretación en particular.

Una secuencia de bytes. Bueno, digamos un byte:
''a''.encode() devuelve b''a'' .

Suficientemente simple. ¿Por qué puedo leer el a ?

Digamos que obtengo el valor ASCII para a , haciendo esto:
printf "%d" "''a"

Devuelve 97 . Bien, bien, el valor entero para el carácter ASCII a . Si interpretamos 97 como ASCII, digamos en un char C, luego obtenemos la letra a . Lo suficientemente justo. Si convertimos la representación de bytes a bits, obtenemos esto:

01100001

2 ^ 0 + 2 ^ 5 + 2 ^ 6 = 97 . Guay.

Entonces, ¿por qué ''a''.encode() devuelve b''a'' lugar de 01100001 ?
Si no tiene una interpretación en particular, ¿no debería estar devolviendo algo como b''01100001'' ?
Parece que lo está interpretando como ASCII.

Alguien mencionó que está llamando a __repr__ en el bytestring, por lo que se muestra en forma legible. Sin embargo, incluso si hago algo como:

with open(''testbytestring.txt'', ''wb'') as f: f.write(b''helloworld'')

Todavía insertará helloworld como una cadena regular en el archivo, no como una secuencia de bytes ... ¿Entonces es un bytestring en ASCII?


Como su nombre lo indica, un bytestring de bytestring (o simplemente una str en Python 2.7) es una cadena de bytes . Y, como han señalado otros, es inmutable.

Es distinto de un str Python3 (o, más descriptivamente, un unicode en Python 2.7) que es una cadena de caracteres abstractos de unicode (también conocido como UTF-32, aunque Python3 agrega una compresión elegante debajo del capó para reducir la huella de memoria real similar a UTF). -8, quizás incluso de una manera más general).

Hay esencialmente tres formas de "interpretar" estos bytes. Puedes mirar el valor numérico de un elemento, así:

>>> ord(b''Hello''[0]) # Python 2.7 str 72 >>> b''Hello''[0] # Python 3 bytestring 72

O puede decirle a Python que emita uno o más elementos al terminal (o un archivo, dispositivo, socket, etc.) como caracteres de 8 bits , como este:

>>> print b''Hello''[0] # Python 2.7 str H >>> import sys # Python 3 bytestring >>> sys.stdout.write(str(b''Hello''[0:1], sys.stdout.encoding)) H

Como Jack insinuó, en este último caso es tu terminal el que interpreta al personaje, no Python (aunque en el caso de Python3 tienes que convertir a str para que sea compatible con futuros terminales que pueden no estar basados ​​en bytes. Esta es la fuente de mucha de la confusión de la OMI).

Finalmente, como ha visto en su propia investigación, también puede hacer que Python interprete una serie de bytestring . Por ejemplo, puede construir un objeto unicode abstracto como este en Python 2.7:

>>> u1234 = unicode(b''/xe1/x88/xb4'', ''utf-8'') >>> u1234 u''/u1234'' >>> type(u1234) <type ''unicode''> >>> len(u1234) 1 >>>

O así en Python 3:

>>> u1234 = str(b''/xe1/x88/xb4'', ''utf-8'') >>> ''//u%04x'' % ord(u1234) /u1234 >>> type(u1234) <class ''str''> >>> len(u1234) 1

Pero la abstracción de Unicode no ocurre automáticamente si no lo desea. El punto de un bytestring es que puede obtener directamente en los bytes. Incluso en el ejemplo de Python2.7 anterior:

>>> len(b''/xe1/x88/xb4'') 3 >>> b''/xe1/x88/xb4''[0] ''/xe1''

También puede hacer otras cosas maravillosas con bytestring s, como saber si bytestring en un espacio reservado dentro de un archivo, enviándolos directamente a través de un socket, calculando el campo de content-length HTTP correctamente y evitando codecs . En resumen, use bytestring s cuando sus datos se procesan y almacenan en bytes.


Es un error común que el texto sea ascii o utf8 o cp1252, y por lo tanto los bytes son texto.

El texto es solo texto, en la forma en que las imágenes son solo imágenes. La cuestión de almacenar texto o imágenes en el disco es cuestión de codificar esos datos en una secuencia de bytes. Hay muchas formas de codificar imágenes en bytes: Jpeg, png, svg, y también muchas formas de codificar texto, ascii, utf8 o cp1252.

Una vez que la codificación ha ocurrido, los bytes son solo bytes. Los bytes ya no son imágenes, se han olvidado de los colores que significan; Aunque un decodificador de formato de imagen puede recuperar esa información. Bytes también han olvidado las letras que solían ser. De hecho, los bytes no recuerdan si eran imágenes o texto. Solo el conocimiento fuera de banda (nombre de archivo, encabezados de medios, etcétera) puede adivinar qué significan esos bytes, e incluso eso puede ser incorrecto (en caso de corrupción de datos)

por lo tanto, en python (py3), tenemos dos tipos para cosas que de otro modo podrían parecer similares; Para el texto, tenemos str , que sabe que es texto; sabe qué letras se supone que significa. No sabe qué bytes pueden ser, ya que las letras no son bytes. También tenemos bytestring , que no sabemos si se trata de texto o imágenes o cualquier otro tipo de datos.

Los dos tipos son superficialmente similares, ya que ambos son secuencias de cosas, pero las cosas de las que son secuencias son bastante diferentes.

Implementacionalmente, str se almacena en la memoria como UCS-? donde el ? La implementación está definida, puede ser UCS4, UCS2 o UCS1, dependiendo de las opciones de tiempo de compilación y qué puntos de código están presentes en la cadena representada.

Editar "pero ¿por qué"?

Algunas cosas que parecen texto se definen realmente en otros términos. Un muy buen ejemplo de esto son los muchos protocolos de internet del mundo. Por ejemplo, HTTP es un protocolo de "texto" que de hecho se define usando la sintaxis ABNF común en los RFC. Estos protocolos se expresan en términos de octetos, no de caracteres, aunque también se puede sugerir una codificación informal:

2.3. Valores terminales

Las reglas se resuelven en una cadena de valores terminales, a veces llamadas
caracteres. En ABNF, un carácter es simplemente un número entero no negativo.
En ciertos contextos, un mapeo específico (codificación) de valores en un
Se especificará el conjunto de caracteres (como ASCII).

Esta distinción es importante, ya que no es posible enviar texto a través de Internet, lo único que puede hacer es enviar bytes. decir "texto pero en ''foo'' la codificación" hace que el formato sea mucho más complejo, ya que los clientes y los servidores ahora tienen que averiguar de alguna manera el negocio de la codificación por su cuenta, esperemos que de la misma manera, ya que finalmente deben pasar los datos como bytes de todas formas. Esto es doblemente inútil ya que estos protocolos rara vez tratan sobre el manejo de textos de todas formas, y es solo una conveniencia para los implementadores. Ni los propietarios del servidor ni los usuarios finales están interesados ​​en leer las palabras Transfer-Encoding: chunked , siempre que tanto el servidor como el navegador lo entiendan correctamente.

En comparación, cuando se trabaja con texto, realmente no importa cómo se codifica. Puedes expresar los "Heävy Mëtal Ümlaüts" como quieras, excepto "Heδvy Mλtal mlaόts"

los distintos tipos le brindan una manera de decir "este valor" significa "texto" o "bytes".


Los objetos de bytes son secuencias inmutables de bytes individuales. Los docs tienen una muy buena explicación de lo que son y cómo usarlos.


Python no sabe cómo representar un bytestring. Ese es el punto.

Cuando genera un carácter con valor 97 en prácticamente cualquier ventana de salida, obtendrá el carácter ''a'' pero eso no es parte de la implementación; Es solo una cosa que sucede a nivel local. Si quieres una codificación, no usas bytestring. Si usas bytestring, no tienes una codificación.

Su artículo sobre los archivos .txt muestra que no ha entendido bien lo que está sucediendo. Usted ve, los archivos de texto plano también no tienen una codificación. Son solo una serie de bytes. El editor de texto traduce estos bytes en letras, pero no existe ninguna garantía de que otra persona que abra su archivo verá lo mismo que usted si se aleja del conjunto común de caracteres ASCII.