tags:

views:

58

answers:

2

I have a data structure that looks like this:

data  =[
{'key_1': { 'calc1': 42, 'calc2': 3.142 } },
{'key_2': { 'calc1': 123.4, 'calc2': 1.414 } },
{'key_3': { 'calc1': 2.718, 'calc2': 0.577 } }
]

I want to be able to save/and load the data into a CSV file with the following format

key,    calc1,   calc2   <- header
key_1,  42,      3.142   <- data rows
key_2,  123.4,   1.414
key_3,  2.718,   0.577

What's the 'Pythonic' way to read/save this data structure to/from a CSV file like the one above?

+5  A: 

I don't think that it would be possible to use csv module, due to all the idiosyncrasies in your requirements and the structure, but you could do it quite easily writing it manually:

>>> with open('test.txt', 'w') as f:
    f.write(','.join(['key', 'calc1', 'calc2']) + '\n')
    f.writelines('{},{},{}'.format(k, *v.values()) + '\n' for l in data for k,v in l.items())
SilentGhost
@silentghost: +1 for the nice and short snippet. I am sure what I would have come up with, would have been a lot more verbose. However, with the succinctness, comes a level of "wtf-ness". Could you please explain the third line - the parameters being passed to writelines()? thanks.
morpheous
perhaps a note that that sorta formatting only works with Python versions of 2.6 onwards
Tshepang
it is just an iterator of string. Each formatted as a comma-separated list, because of nested-ness of your `data`, I had to iterate twice.
SilentGhost
@silentghost: also, how can you be sure that the keys returned in l.items() will be correctly ordered (i.e. will be in the same column in the generated CSV file)?.
morpheous
@Tshepang: there's nothing preventing you from changing it to the classical `%` formatting.
SilentGhost
@morpheous: given the same key names, `dict.items()` returns value in a predictable order. You could of course modify this example to return values in the order you desire.
SilentGhost
@silent: thanks for the clarification
morpheous
@SilentGhost: That's not the point. I was merely was a suggestion that in your answer, you should have indicated that the formatting was for versions 2.6 onwards.
Tshepang
@Tshepand: it's a formatting recommended in a current stable version of Python!
SilentGhost
A: 

Just to show a version that does use the csv module:

from csv import DictWriter

data  =[
{'key_1': { 'calc1': 42, 'calc2': 3.142 } },
{'key_2': { 'calc1': 123.4, 'calc2': 1.414 } },
{'key_3': { 'calc1': 2.718, 'calc2': 0.577 } }
]

with open('test.csv', 'wb') as f:
    writer = DictWriter(f, ['key', 'calc1', 'calc2'])
    writer.writerow(dict(zip(writer.fieldnames, writer.fieldnames))) # no automatic header :-(
    for i in data:
        key, values = i.items()[0] # each dict in data contains only one entry
        writer.writerow(dict(key=key, **values)) # first make a new dict merging the key and the values
Steven