Estaba tratando de construir este objeto de bytes en Python 3:
b'3\r\n'
así que probé lo obvio (para mí) y encontré un comportamiento extraño:
>>> bytes(3) + b'\r\n'
b'\x00\x00\x00\r\n'
Aparentemente:
>>> bytes(10)
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
No he podido ver ningún indicador sobre por qué la conversión de bytes funciona de esta manera al leer la documentación. Sin embargo, encontré algunos mensajes sorpresa en este problema de Python acerca de agregar format
bytes (ver también el formato Python 3 bytes ):
http://bugs.python.org/issue3982
Esto interactúa aún peor con rarezas como bytes (int) que devuelven ceros ahora
y:
Sería mucho más conveniente para mí si bytes (int) devuelve la ASCIIFICACIÓN de ese int; pero sinceramente, incluso un error sería mejor que este comportamiento. (Si quisiera este comportamiento, que nunca he tenido, prefiero que sea un método de clase, invocado como "bytes.zeroes (n)").
¿Alguien puede explicarme de dónde viene este comportamiento?
fuente
3 .to_bytes
Respuestas:
Así fue diseñado, y tiene sentido porque, por lo general, llamaría
bytes
a un entero iterable en lugar de a un único entero:Los documentos indican esto , así como la cadena de documentos para
bytes
:fuente
bytes
es solo un alias parastr
, lo que significa quebytes([3])
le da'[3]'
.bytes([n])
solo funciona para int n de 0 a 255. Para cualquier otra cosa, aumentaValueError
.bytes([3])
todavía es diferente de lo que quería el OP, es decir, el valor de byte utilizado para codificar el dígito "3" en ASCII, es decir.bytes([51])
, que esb'3'
, nob'\x03'
.bytes(500)
crea una cadena de bytes con len == 500. No crea una cadena de bytes que codifique el entero 500. Y estoy de acuerdo en quebytes([500])
no puede funcionar, por lo que esa es la respuesta incorrecta también. Probablemente la respuesta correcta seaint.to_bytes()
para versiones> = 3.1.Desde python 3.2 puedes hacer
https://docs.python.org/3/library/stdtypes.html#int.to_bytes
En consecuencia
x == int_from_bytes(int_to_bytes(x))
,. Tenga en cuenta que esta codificación solo funciona para enteros sin signo (no negativos).fuente
b"3"
a partir3
, como la pregunta se refiere. (b"\x03"
Puede usar el paquete de la estructura :
El ">" es el orden de bytes (big-endian) y el "I" es el carácter de formato . Por lo tanto, puede ser específico si desea hacer otra cosa:
Esto funciona igual en python 2 y python 3 .
Nota: la operación inversa (bytes a int) se puede hacer con descomprimir .
fuente
I
,H
, yB
trabajo hasta2**k - 1
donde k es 32, 16, y 8 respectivamente. Para entradas más grandes aumentanstruct.error
.b'3\r\n'
, es decir, una cadena de bytes que contiene el carácter ASCII "3", no el carácter ASCII "\ x03"\x03
, y la solución si solo quieresb'3'
es trivial. La razón citada por ABB es mucho más plausible ... o al menos comprensible.bytes([x])
y(x).to_bytes()
en Python 3.5. Eso fue inesperado.Python 3.5+ presenta% -interpolation (
printf
formato de estilo) para bytes :Ver PEP 0461 - Agregar formato% a bytes y bytearray .
En versiones anteriores, podría usar
str
y.encode('ascii')
el resultado:Nota: es diferente de lo que
int.to_bytes
produce :fuente
La documentación dice:
La secuencia:
Es el carácter '3' (51 decimal) el carácter '\ r' (13) y '\ n' (10).
Por lo tanto, la forma lo trataría como tal, por ejemplo:
Probado en IPython 1.1.0 y Python 3.2.3
fuente
bytes(str(n), 'ascii') + b'\r\n'
ostr(n).encode('ascii') + b'\r\n'
. ¡Gracias! :)"{}\r\n".format(n).encode()
tampoco creo que haya ningún daño al usar la codificación utf8 predeterminada¡La ASCIIFICACIÓN de 3
"\x33"
no lo es"\x03"
!Eso es lo que hace Python,
str(3)
pero sería totalmente incorrecto para los bytes, ya que deberían considerarse conjuntos de datos binarios y no ser abusados como cadenas.La forma más fácil de lograr lo que desea es
bytes((3,))
, que es mejor quebytes([3])
porque inicializar una lista es mucho más costoso, así que nunca use listas cuando pueda usar tuplas. Puede convertir enteros más grandes conint.to_bytes(3, "little")
.Inicializar bytes con una longitud determinada tiene sentido y es lo más útil, ya que a menudo se usan para crear algún tipo de búfer para el que necesita asignar memoria de un tamaño determinado. A menudo uso esto al inicializar matrices o expandir algún archivo escribiendo ceros en él.
fuente
b'3'
esb'\x33'
, nob'\x32'
. (b)(3)
no es una tupla: debe agregar una coma. (c) El escenario de inicializar una secuencia con ceros no se aplica a losbytes
objetos, ya que son inmutables (sin embargo, tiene sentido parabytearray
s).bytes
ybytearray
, creo que es principalmente una cuestión de consistencia. Pero también es útil si desea insertar algunos ceros en un búfer o archivo, en cuyo caso solo se usa como fuente de datos.int
(incluyendo Python2long
) se puede convertirbytes
usando la siguiente función:La conversión inversa puede ser realizada por otro:
Ambas funciones funcionan tanto en Python2 como en Python3.
fuente
Tenía curiosidad sobre el rendimiento de varios métodos para un solo int en el rango
[0, 255]
, así que decidí hacer algunas pruebas de tiempo.Sobre la base de los tiempos de abajo, y de la tendencia general he observado de tratar muchos valores y configuraciones diferentes,
struct.pack
que parece ser el más rápido, seguido deint.to_bytes
,bytes
y constr.encode
(como era de esperar) la más lenta. Tenga en cuenta que los resultados muestran algunos más variación que se representa, yint.to_bytes
ybytes
en ocasiones velocidad con conmutación de rango durante las pruebas, perostruct.pack
es claramente el más rápido.Resultados en CPython 3.7 en Windows:
Módulo de prueba (nombrado
int_to_byte.py
):fuente
[0, 255]
. Supongo que por "indicador incorrecto" quiere decir que mis mediciones no fueron lo suficientemente generales como para adaptarse a la mayoría de las situaciones. ¿O fue pobre mi metodología de medición? Si es lo último, me interesaría saber lo que tiene que decir, pero si es lo primero, nunca afirmé que mis medidas fueran genéricas para todos los casos de uso. Para mi situación (tal vez de nicho), solo estoy tratando con entradas en el rango[0, 255]
, y esa es la audiencia que pretendía abordar con esta respuesta. ¿No estaba clara mi respuesta? Puedo editarlo para mayor claridad ...bytes((i,))
lugar debytes([i])
porque la lista es más compleja, use más memoria y tarde mucho en inicializar. En este caso, por nada.Aunque la respuesta previa de brunsgaard es una codificación eficiente, solo funciona para enteros sin signo. Este se basa en él para funcionar tanto con enteros con signo como sin signo.
Para el codificador,
(i + ((i * signed) < 0)).bit_length()
se usa en lugar de soloi.bit_length()
porque este último conduce a una codificación ineficiente de -128, -32768, etc.Crédito: CervEd por arreglar una ineficiencia menor.
fuente
int_to_bytes(-128, signed=True) == (-128).to_bytes(1, byteorder="big", signed=True)
esFalse
-128
,-32768
etc.(i+(signed*i<0)).bit_length()
El comportamiento proviene del hecho de que en Python antes de la versión 3
bytes
era solo un alias parastr
. En Python3.xbytes
hay una versión inmutable debytearray
: tipo completamente nuevo, no compatible con versiones anteriores.fuente
De bytes docs :
Luego, de bytearray docs :
Tenga en cuenta que difiere del comportamiento 2.x (donde x> = 6), donde
bytes
es simplementestr
:PEP 3112 :
fuente
Algunas respuestas no funcionan con grandes números.
Convierta un entero a la representación hexadecimal, luego conviértalo a bytes:
Resultado:
fuente
int.to_bytes
funciona con cualquier número entero.Si la pregunta es cómo convertir un entero en sí (no su equivalente de cadena) en bytes, creo que la respuesta sólida es:
Más información sobre estos métodos aquí:
fuente