Ничего сверхсложного, но если скорость имеет значение, функции верхнего уровня модуля struct
являются обертками, которые должны повторно проверять кэш для фактического экземпляра struct.Struct
, соответствующего строке формата;в то время как вы должны создавать отдельные строки формата, вы можете решить часть проблемы со скоростью, избегая повторной проверки кэша.
Вместо выполнения:
buffer = memoryview(somedata)
allresults = []
while buffer:
allresults += struct.unpack_from('<10sHHb', buffer)
buffer = buffer[struct.calcsize('<10sHHb'):]
allresults += struct.unpack_from('>llh', buffer)
buffer = buffer[struct.calcsize('>llh'):]
Вы бы сделали:
buffer = memoryview(somedata)
structa = struct.Struct('<10sHHb')
structb = struct.Struct('>llh')
allresults = []
while buffer:
allresults += structa.unpack_from(buffer)
buffer = buffer[structa.size:]
allresults += structb.unpack_from(buffer)
buffer = buffer[structb.size:]
Нет, это не очень хорошо выглядит, и выигрыш в скорости вряд ли вас унесет.Но у вас есть странные данные, так что это наименее хрупкое решение.
Если вы хотите излишне умные / хрупкие решения, вы можете сделать это с помощью ctypes
custom Structure
s., вложив BigEndianStructure
(s) внутрь LittleEndianStructure
или наоборот.Для вашего примера формата:
from ctypes import *
class BEStruct(BigEndianStructure):
_fields_ = [('x', 2 * c_long), ('y', c_short)]
_pack_ = True
class MainStruct(LittleEndianStructure):
_fields_ = [('a', 10 * c_char), ('b', 2 * c_ushort), ('c', c_byte), ('big', BEStruct)]
_pack_ = True
даст вам такую структуру, которую вы могли бы сделать:
mystruct = MainStruct()
memoryview(mystruct).cast('B')[:] = bytes(range(25))
, и тогда вы получите результаты в ожидаемом порядке, например:
>>> hex(mystruct.b[0]) # Little endian as expected in main struct
'0xb0a'
>>> hex(mystruct.big.x[0]) # Big endian from inner big endian structure
'0xf101112'
Будучи умным в некотором смысле, он, вероятно, будет работать медленнее (поиск по атрибутам ctypes
странно медленен в моем опыте), и в отличие от struct
функций модуля, вы не можете просто распаковать в top-именованные переменные в одной строке, доступ к атрибутам полностью.