Python's struct library is too low-level for direct usage. This recipe (only 40 lines) shows how it can be turned into more developer-friendly tool.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57  | from struct import calcsize, pack, unpack
class ConcreteRecord:
    def __init__(self, fields, data=None):
        self._fields = fields
        if data == None: return
        for f in fields:
            name,fmt,start,stop = f
            val = unpack(fmt, data[start:stop])
            if len(val) == 1: val=val[0]
            self.__dict__[name] = val
    def __str__(self):
        lst = []
        for f in self._fields:
            name,fmt,start,stop = f
            val = self.__dict__.get(name)
            if type(val) in (tuple,list):  # U
                lst += [pack(fmt,*val)]    # G
            else:                          # L
                lst += [pack(fmt,val)]     # Y
        return ''.join(lst)
class RecordFactory:
    def __init__(self,record_fmt):
        self.fields = []
        pos = 0
        for field in record_fmt.split():
            if field[0] == "#": continue
            fmt,name = field.split('.')
            size = calcsize(fmt)
            self.fields += [(name,fmt,pos,pos+size)]
            pos += size
    def build(self, data):
        return ConcreteRecord(self.fields, data)
#### EXAMPLE ##################################################################
myrf = RecordFactory("""
    4B.ip
    >H.port
    >I.session_id
""")
r = myrf.build("\x00\x01\x02\x03" + "\x00\x04" + "\xFE\xDC\xBA\x98")
print "ip:        ", r.ip
print "port:      ", r.port
print "session_id:", r.session_id
r.port       = 1029       # equals 0x0405
r.session_id = 101124105  # equals 0x06070809
import binascii
print "record_str:", binascii.hexlify(str(r))
 | 
Four lines of code are marked as "UGLY" because I don't have an idea how to write this code as one statement (my intuition tells me that it is possible). I would be grateful for any hints.
    Tags: database
  
  
Download
Copy to clipboard
dpkt metaclass. check out http://monkey.org/~dugsong/dpkt/ for another implementation of the same idea, using a simple metaclass in dpkt.py.
Using a byte as flags. After creating a ConcreteRecord this class can be used to attach boolean flag names to a byte.