是否有一种优雅的方式来使用struct和namedtuple而不是这个?

0xC*_*22L 5 python struct binaryfiles namedtuple

我正在读一个由C语言组成的二进制文件,它们看起来像这样:

typedef _rec_t
{
  char text[20];
  unsigned char index[3];
} rec_t;
Run Code Online (Sandbox Code Playgroud)

现在我能够将它解析成具有23个不同值的元组,但是如果我可以使用namedtuple将前20个字节text和剩余的3个字节组合成,则更愿意index.我怎样才能做到这一点?基本上不是一个23个值的元组,而是我更喜欢分别有两个20和3个元组的元组,并使用"自然名称"来访问它们,即通过namedtuple.

我目前使用的格式"20c3B"进行struct.unpack_from().

注意:调用时,字符串中有许多连续记录parse_text.


我的代码(剥离到相关部分):

#!/usr/bin/env python
import sys
import os
import struct
from collections import namedtuple

def parse_text(data):
    fmt = "20c3B"
    l = len(data)
    sz = struct.calcsize(fmt)
    num = l/sz
    if not num:
        print "ERROR: no records found."
        return
    print "Size of record %d - number %d" % (sz, num)
    #rec = namedtuple('rec', 'text index')
    empty = struct.unpack_from(fmt, data)
    # Loop through elements
    # ...

def main():
    if len(sys.argv) < 2:
        print "ERROR: need to give file with texts as argument."
        sys.exit(1)
    s = os.path.getsize(sys.argv[1])
    f = open(sys.argv[1])
    try:
        data = f.read(s)
        parse_text(data)
    finally:
        f.close()

if __name__ == "__main__":
    main()
Run Code Online (Sandbox Code Playgroud)

Sam*_*lar 6

根据文档:http://docs.python.org/library/struct.html

可以通过将解压缩字段分配给变量或将结果包装在命名元组中来命名解压缩字段:

>>> record = 'raymond   \x32\x12\x08\x01\x08'
>>> name, serialnum, school, gradelevel = unpack('<10sHHb', record)

>>> from collections import namedtuple
>>> Student = namedtuple('Student', 'name serialnum school gradelevel')
>>> Student._make(unpack('<10sHHb', record))
Student(name='raymond   ', serialnum=4658, school=264, gradelevel=8)
Run Code Online (Sandbox Code Playgroud)

所以在你的情况下

>>> import struct
>>> from collections import namedtuple
>>> data = "1"*23
>>> fmt = "20c3B"
>>> Rec = namedtuple('Rec', 'text index') 
>>> r = Rec._make([struct.unpack_from(fmt, data)[0:20], struct.unpack_from(fmt, data)[20:]])
>>> r
Rec(text=('1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1'), index=(49, 49, 49))
>>>
Run Code Online (Sandbox Code Playgroud)

切片解包变量可能是一个问题,如果格式是fmt = "20si"标准我们不返回顺序字节的东西,我们不需要这样做.

>>> import struct
>>> from collections import namedtuple
>>> data = "1"*24
>>> fmt = "20si"
>>> Rec = namedtuple('Rec', 'text index') 
>>> r = Rec._make(struct.unpack_from(fmt, data))
>>> r
Rec(text='11111111111111111111', index=825307441)
>>>
Run Code Online (Sandbox Code Playgroud)

  • 我们真的打算使用`_make`吗?领先的下划线是可疑的...... (2认同)