【问题标题】:Python struct.unpack(ing) when there are multiple byte-orders?有多个字节顺序时的Python struct.unpack(ing)?
【发布时间】:2019-07-16 02:52:36
【问题描述】:

我有一个函数可以读取二进制文件,然后使用 struct.unpack() 解压缩文件的内容。我的功能工作得很好。如果/当我使用长的“格式”字符串解压缩整个文件时,它会更快。问题是有时字节对齐会发生变化,因此我的格式字符串(无效)看起来像 'llh' (这只是一个示例(它们通常更长))。是否有任何超光滑/pythonic 的方式来处理这种情况?

【问题讨论】:

    标签: python python-3.x performance binaryfiles iterable-unpacking


    【解决方案1】:

    没什么特别的,但是如果速度很重要,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 自定义Structures,将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 模块函数不同,您不能只解压缩到顶级命名变量中单行,一路属性访问。

    【讨论】:

      猜你喜欢
      • 2018-07-28
      • 1970-01-01
      • 1970-01-01
      • 2010-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-16
      相关资源
      最近更新 更多