Endianness de enteros en Python
-
05-07-2019 - |
Pregunta
Estoy trabajando en un programa donde almaceno algunos datos en un número entero y los proceso a nivel de bits. Por ejemplo, podría recibir el número 48, que procesaré bit por bit. En general, el endianness de los enteros depende de la representación de los enteros en la máquina, pero ¿Python hace algo para garantizar que los ints siempre sean little-endian? ¿O necesito verificar la endianness como lo haría en C y luego escribir un código separado para los dos casos?
Pregunto porque mi código se ejecuta en una máquina Sun y, aunque en el que se está ejecutando ahora usa procesadores Intel, es posible que tenga que cambiarme a una máquina con procesadores Sun en el futuro, lo que sé que es big endian.
Solución
int
de Python tiene la misma endianness que el procesador en el que se ejecuta. El módulo struct
le permite convertir los blobs de bytes en pulgadas (y viceversa, y algunos otros tipos de datos también) en formas nativas, little-endian o big-endian, dependiendo de cadena de formato que elija: inicie el formato con @
o sin carácter de endianness para usar endianness nativo (y tamaños nativos; todo lo demás usa tamaños estándar), ' ~ 'para nativo,' < ' para little-endian, '>' o '!' para big-endian.
Esto es byte a byte, no bit a bit; No estoy seguro de a qué se refiere exactamente con el procesamiento bit a bit en este contexto, pero supongo que puede adaptarse de manera similar.
Para rápido " volumen " procesando en casos simples, considere también el array - el fromstring y
tostring
pueden operar en un gran número de bytes rápidamente, y el método byteswap
puede brindarle el " otro " endianness (nativo a no nativo o viceversa), de nuevo rápidamente y para una gran cantidad de elementos (toda la matriz).
Otros consejos
Si necesita procesar sus datos 'bitwise', entonces cadena de bits
módulo podría ser de ayuda para usted. También puede lidiar con el endianness entre plataformas (al menos en la última generación de troncales, que se lanzará en los próximos días).
El struct
es el mejor método estándar de Tratar la endianidad entre plataformas. Por ejemplo, este paquete empaqueta y desempaqueta los enteros 1, 2, 3 en dos 'cortos' y uno 'largo' (2 y 4 bytes en la mayoría de las plataformas) utilizando endianness nativo:
>>> from struct import *
>>> pack('hhl', 1, 2, 3)
'\x00\x01\x00\x02\x00\x00\x00\x03'
>>> unpack('hhl', '\x00\x01\x00\x02\x00\x00\x00\x03')
(1, 2, 3)
Para verificar el endianness de la plataforma mediante programación, puede utilizar
>>> import sys
>>> sys.byteorder
que devolverá " big "
o " little "
.
¿Cuándo?
Al realizar operaciones bitwise, el int in tendrá la misma endianess que los ints que usted ingresa. No necesita verificar eso. Solo debe preocuparse por esto al convertir a / desde secuencias de bytes, en ambos idiomas, afaik.
En Python, usas el módulo struct para esto, más comúnmente struct.pack () y struct.unpack ().
El siguiente fragmento de código te dirá si el valor predeterminado de tu sistema es little endian (de lo contrario es big-endian)
import struct
little_endian = (struct.unpack('<I', struct.pack('=I', 1))[0] == 1)
Sin embargo, tenga en cuenta que esto no afectará el comportamiento de los operadores bitwise: 1 < < 1
es igual a 2
independientemente de la endianness predeterminada de su sistema.