7

struct.unpack will unpack data into a tuple. Is there an equivalent that will store data into a dict instead?

In my particular problem, I am dealing with a fixed-width binary format. I want to be able, in one fell swoop, to unpack and store the values in a dict (currently I manually walk through the list and assign dict values)

3
  • 2
    I don't think so. But the dict constructor can take a list or iterator of (name, value) pairs to initialize with. That might help you.
    – Keith
    Commented Aug 23, 2011 at 1:47
  • You might also be interested in namedtuple if you don't need to modify the object after creating it.
    – kindall
    Commented Aug 23, 2011 at 1:56
  • 2
    What do you expect the keys to be?
    – FogleBird
    Commented Aug 23, 2011 at 2:08

3 Answers 3

13

If you're on 2.6 or newer you can use namedtuple + struct.pack/unpack like this:

import collections
import struct

Point = collections.namedtuple("Point", "x y z")

data = Point(x=1, y=2, z=3)

packed_data = struct.pack("hhh", *data)
data = Point(*struct.unpack("hhh", packed_data))

print data.x, data.y, data.z
0
9

Do you want something like this?

keys = ['x', 'y', 'z']
values = struct.unpack('<III', data)
d = dict(zip(keys, values))
4
  • that's what im doing now. I was hoping for something a bit slicker
    – Foo Bah
    Commented Aug 23, 2011 at 2:12
  • its a list that is being walked through (unless zip does something clever that doesnt involve walking through the list).
    – Foo Bah
    Commented Aug 23, 2011 at 2:22
  • 3
    I feel this solution is fine, and already slicker than mucking around with collections.namedtuple
    – wim
    Commented Aug 23, 2011 at 3:59
  • just as an aside this method is MUCH faster than the named tuple version Commented Dec 21, 2019 at 21:45
5

The struct documentation shows an example of unpacking directly into a namedtuple. You can combine this with namedtuple._asdict() to get your one swell foop:

>>> import struct
>>> from collections import namedtuple
>>> record = 'raymond   \x32\x12\x08\x01\x08'
>>> Student = namedtuple('Student', 'name serialnum school gradelevel')
>>> Student._asdict(Student._make(struct.unpack('<10sHHb', record)))
{'school': 264, 'gradelevel': 8, 'name': 'raymond   ', 'serialnum': 4658}
>>> 

If it matters, note that in Python 2.7 _asdict() returns an OrderedDict...

8
  • Heh probably should have checked the web doc. No indication of this in the python help(struct)
    – Foo Bah
    Commented Aug 23, 2011 at 3:03
  • 3
    interesting answer. i see it's a dynamically generated function, but why is _asdict() with a prepended underscore?
    – wim
    Commented Aug 23, 2011 at 3:58
  • 1
    @FogleBird - not sure what you mean by private methods. namedtuple._asdict() is documented here: python.org/doc//current/library/…. And I took the usage of namedtuple._make() directly from the documentation linked in the answer. What's the recommended best practice here?
    – mtrw
    Commented Aug 24, 2011 at 1:38
  • 1
    You can rewrite the fifth line more concisely as Student(*struct.unpack('<10sHHb', record))._asdict() Commented Nov 20, 2018 at 9:22
  • 1
    this solution is significantly slower than dict(zip(keys,struct.unpack(...))) Commented Dec 21, 2019 at 21:46

Not the answer you're looking for? Browse other questions tagged or ask your own question.