¿Cuál es la mejor manera de hacer la manipulación de Bit Field en Python?

Estoy leyendo un protocolo de flujo de transporte MPEG a través de UDP y tiene algunos campos de bits funky (longitud 13 por ejemplo). Estoy usando la biblioteca “struct” para hacer el desempaque amplio, pero ¿hay una forma sencilla de decir “Agarrar los siguientes 13 bits” en lugar de modificar manualmente la manipulación de los bits? Me gustaría algo como la forma en que C realiza los campos de bits (sin tener que volver a C).

Sugerencias?

Es una pregunta frecuente. Hay una entrada en el libro de cocina ASPN que me ha servido en el pasado.

Y hay una página extensa de requisitos que a una persona le gustaría ver en un módulo que hace esto.

El módulo de cadena de bits está diseñado para solucionar este problema. Le permitirá leer, modificar y construir datos utilizando bits como los bloques de construcción básicos. Las últimas versiones son para Python 2.6 o posterior (incluyendo Python 3) pero la versión 1.0 también es compatible con Python 2.4 y 2.5.

Un ejemplo relevante para usted podría ser este, que elimina todos los paquetes nulos de un flujo de transporte (y posiblemente utiliza su campo de 13 bits):

from bitstring import Bits, BitStream # Opening from a file means that it won't be all read into memory s = Bits(filename='test.ts') outfile = open('test_nonull.ts', 'wb') # Cut the stream into 188 byte packets for packet in s.cut(188*8): # Take a 13 bit slice and interpret as an unsigned integer PID = packet[11:24].uint # Write out the packet if the PID doesn't indicate a 'null' packet if PID != 8191: # The 'bytes' property converts back to a string. outfile.write(packet.bytes) 

Aquí hay otro ejemplo que incluye la lectura de bitstreams:

 # You can create from hex, binary, integers, strings, floats, files... # This has a hex code followed by two 12 bit integers s = BitStream('0x000001b3, uint:12=352, uint:12=288') # Append some other bits s += '0b11001, 0xff, int:5=-3' # read back as 32 bits of hex, then two 12 bit unsigned integers start_code, width, height = s.readlist('hex:32, 2*uint:12') # Skip some bits then peek at next bit value s.pos += 4 if s.peek(1): flags = s.read(9) 

Puede usar la notación de división estándar para dividir, eliminar, revertir, sobrescribir, etc. a nivel de bits, y hay funciones de buscar, reemplazar, dividir, etc. a nivel de bits. También se admiten diferentes endiannesses.

 # Replace every '1' bit by 3 bits s.replace('0b1', '0b001') # Find all occurrences of a bit sequence bitposlist = list(s.findall('0b01000')) # Reverse bits in place s.reverse() 

La documentación completa está aquí .