¿Cómo leer números enteros de un archivo que son 24bit y little endian usando Python?

¿Hay una manera fácil de leer estos números enteros en? Preferiría un método incorporado, pero supongo que es posible hacerlo con algunas operaciones de bits.
Aclamaciones

editar
Pensé en otra forma de hacerlo que sea diferente a las formas a continuación y en mi opinión es más clara. Se rellena con ceros en el otro extremo, luego cambia el resultado. No, si es necesario, porque el cambio se llena con lo que sea inicialmente el msb.

struct.unpack('> 8 

El módulo de struct de Python le permite interpretar los bytes como diferentes tipos de estructura de datos, con control sobre la endianidad.

Si lees un solo número de tres bytes del archivo, puedes convertirlo así:

 struct.unpack(' 

El módulo no parece admitir palabras de 24 bits, por lo tanto, el relleno '\0' .

EDITAR: Los números firmados son más complicados. Puede copiar el bit alto y establecer el bit alto en cero porque se mueve al lugar más alto de 4 bytes (el último \xff tiene):

 struct.unpack(' 

O, para python3 ( bytes es una palabra reservada, al verificar un byte de una matriz de bytes se obtiene un int ):

 struct.unpack(' 

¿Sus enteros de 24 bits están firmados o no? Bigendian o littleendian?

 struct.unpack('I', '\x00' + bytes)[0] # unsigned bigendian 

Firmado es un poco más complicado … obtenga el valor sin firmar como se indica arriba, luego haga esto:

 signed = unsigned if not (unsigned & 0x800000) else unsigned - 0x1000000 

Si no le importa usar una biblioteca externa, mi módulo de cadenas de bits podría ser útil aquí.

 from bitstring import ConstBitStream s = ConstBitStream(filename='some_file') a = s.read('uintle:24') 

Esto se lee en los primeros 24 bits y se interpreta como un entero little-endian sin firmar. Después de la lectura, los s.pos se configuran en 24 (la posición del bit en el flujo), para que pueda leer más. Por ejemplo, si desea obtener una lista de los siguientes 10 enteros con signo, podría usar

 l = s.readlist('10*intle:24') 

o si lo prefiere, puede usar rebanadas y propiedades y no molestarse con las lecturas:

 a = s[0:24].uintle 

Otra alternativa si ya tiene los 3 bytes de datos de su archivo es simplemente crear e interpretar:

 a = ConstBitStream(bytes=b'abc').uintle 

Un poco tarde, pero aquí hay algo que podría ser útil en esta situación. Se basa en la respuesta actualizada del OP, pero la integra en una función que lee una lista completa de valores de un archivo empaquetado de 24 bits. Lo hace principalmente con estructura, así que creo que debería ser razonablemente rápido.

  def int24_to_int(self, input_data): bytelen = len(input_data) frames = bytelen/3 triads = struct.Struct('3s' * frames) int4byte = struct.Struct('> 8 for i in triads.unpack(input_data)] return result