Qual é a melhor maneira de manipular Bit Field em Python?
-
09-06-2019 - |
Pergunta
Estou lendo um protocolo MPEG Transport Stream sobre UDP e ele contém alguns campos de bits estranhos (comprimento 13, por exemplo).Estou usando a biblioteca "struct" para fazer a descompactação ampla, mas existe uma maneira simples de dizer "Pegue os próximos 13 bits" em vez de precisar ajustar manualmente a manipulação de bits?Eu gostaria de algo parecido com o modo como C faz campos de bits (sem precisar reverter para C).
Sugestões?
Solução
É uma pergunta frequente.Há uma Livro de receitas ASPN entrada nele que me serviu no passado.
E há um extensa página de requisitos que uma pessoa gostaria de ver em um módulo fazendo isso.
Outras dicas
O cadeia de bits O módulo foi projetado para resolver exatamente esse problema.Ele permitirá que você leia, modifique e construa dados usando bits como blocos de construção básicos.As versões mais recentes são para Python 2.6 ou posterior (incluindo Python 3), mas a versão 1.0 também suporta Python 2.4 e 2.5.
Um exemplo relevante para você pode ser este, que remove todos os pacotes nulos de um fluxo de transporte (e possivelmente usa seu 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)
Aqui está outro exemplo, incluindo a leitura de fluxos de bits:
# 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)
Você pode usar a notação de fatia padrão para fatiar, excluir, reverter, substituir, etc.no nível de bit, e há localização, substituição, divisão, etc.funções.Diferentes endiannesses também são suportados.
# 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()
A documentação completa é aqui.