[英]Python struct.unpack(ing) when there are multiple byte-orders?
我有一个函数读取二进制文件,然后使用struct.unpack()解压缩文件的内容。 我的功能很好用。 如果/当我使用长“格式”字符串解压缩整个文件时,它会更快。 问题是有时字节对齐会改变,所以我的格式字符串(无效)看起来像'<10sHHb> llh'(这只是一个例子(它们通常更长))。 是否有任何超光滑/ pythonic方式处理这种情况?
没有什么超级流畅,但如果速度很重要, 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
自定义Structure
,在LittleEndianStructure
嵌套BigEndianStructure
,反之亦然。 对于您的示例格式:
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
慢( ctypes
属性查找在我的经验中非常慢),并且与struct
module函数不同,你不能只在一行中解压缩到顶级命名变量,它的属性访问权限一路走来。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.