Windy71
Windy71

Reputation: 909

Update a csv with dict values in a loop without keys

I can make a csv with from a dict ok using csv.Dictwriter but cannot figure out how to make a function to append a new dicts values to the csv file and ensuring that a value is added to the correct column of the csv to preserve the link between key and value.

[Added to clarify why I need this in a loop] In the code im writing I need to write headers to a csv and then I have a measuring loop, in the loop I receive a dict of all the measurement results and want to write this to the csv file - then the dict will be rewritten with new values when the next iteration of the loop happens - I just dent know how to code something that simulates that without the dict of dicts I went with.

Code

import csv
print('\n'*3)

adict = {"Gizmo" : 1, "Line" : 1, "Height" : 6.0, "Weight" : 9.7, "Width" : 90}
bdict = {"Gizmo" : 1, "Line" : 2, "Height" : 5.8, "Weight" : 9.9, "Width" : 89.2}
cdict = {"Gizmo" : 1, "Line" : 3, "Height" : 6.3, "Weight" : 11.0, "Width" : 91.9}
ddict = {"Gizmo" : 1, "Line" : 4, "Height" : 6.2, "Weight" : 7.7, "Width" : 89.4}
my_dict = {"a": adict, "b": bdict, "c" : cdict, "d" : ddict}

def make_csv_with_headers(my_csv_file):
    csv_file = my_csv_file
    try:
        with open(csv_file, 'w') as csvfile:
            writer = csv.DictWriter(csvfile, fieldnames = my_dict["a"].keys())
            writer.writeheader()
            #for data in adict:
                #writer.writerow(data)
    except IOError:
        print("I/O error")


def update_csv(my_csv_file):
    csv_file = my_csv_file
    with open(csv_file, 'w') as csvfile:
        writer = csv.DictWriter(csvfile)
        for k, v in adict.items():
            writer.writerow(v)


make_csv_with_headers("a_data.csv")
for k,v in my_dict.items():
    print(v,'\n')
    update_csv("a_data.csv")

Tried and failed

def update_csv_2():
    myfile = open('aa.csv', 'w')

    with open(myfile, 'w') as f:   
        fnames = my_dict["a"].keys()
        writer = csv.DictWriter(f, fieldnames=fnames)    
        writer.writeheader()
        writer.writerow(my_dict["a"].values())
        writer.writerow(my_dict["b"].values())
        writer.writerow(my_dict["c"].values())
        writer.writerow(my_dict["d"].values())

desired output #csv file

Gizmo,Line,Height,Weight,Width
1,1,6.0,9.7,90
1,2,5.8,9.9,89.2
1,3,6.3,11.0,91.9
1,4,6,2,7.7,89.4

code for when you have to use this in a loop

import csv
from csv import writer
from csv import DictWriter

adict = {"Gizmo" : 1, "Line" : 1, "Height" : 6.0, "Weight" : 9.7, "Width" : 90}
bdict = {"Gizmo" : 1, "Line" : 2, "Height" : 5.8, "Weight" : 9.9, "Width" : 89.2}
cdict = {"Gizmo" : 1, "Line" : 3, "Height" : 6.3, "Weight" : 11.0, "Width" : 91.9}
ddict = {"Gizmo" : 1, "Line" : 4, "Height" : 6.2, "Weight" : 7.7, "Width" : 89.4}
my_dict = {"a": adict, "b": bdict, "c" : cdict, "d" : ddict}
my_dict2 = [adict,bdict,cdict,ddict]


def make_csv_with_header(filename):
    headers = ["Gizmo", "Line", "Height", "Weight", "Width"]
    with open(filename, 'w') as f:
            writer_object = writer(f)
            writer_object.writerow(headers)
            f.close()


def append_csv(filename, mydict): 
    field_names = ["Gizmo", "Line", "Height", "Weight", "Width"] 
    # Open your CSV file in append mode, Create a file object for this file
    with open('a3.csv', 'a') as f_object: 
        # Pass the file object and a list  of column names to DictWriter() You will get a object of DictWriter
        dictwriter_object = DictWriter(f_object, fieldnames=field_names)
        #Pass the dictionary as an argument to the Writerow()
        dictwriter_object.writerow(mydict)
        #Close the file object
        f_object.close()


# make initial csv with headers
make_csv_with_header("a3.csv")
# appending dict to csv
for dicty in my_dict2:
    append_csv("a3.csv", dicty)

Upvotes: 0

Views: 245

Answers (1)

MegaIng
MegaIng

Reputation: 7886

You don't want to repeatly open and close the .csv file. Especially if you open in w mode, the old content will be gone. Just open once:

import csv
print('\n'*3)

adict = {"Gizmo" : 1, "Line" : 1, "Height" : 6.0, "Weight" : 9.7, "Width" : 90}
bdict = {"Gizmo" : 1, "Line" : 2, "Height" : 5.8, "Weight" : 9.9, "Width" : 89.2}
cdict = {"Gizmo" : 1, "Line" : 3, "Height" : 6.3, "Weight" : 11.0, "Width" : 91.9}
ddict = {"Gizmo" : 1, "Line" : 4, "Height" : 6.2, "Weight" : 7.7, "Width" : 89.4}
my_dict = {"a": adict, "b": bdict, "c" : cdict, "d" : ddict}


with open("a_data.csv", 'w') as csvfile:
    writer = csv.DictWriter(csvfile, fieldnames = my_dict["a"].keys())
    for k, v in my_dict.items():
        print(v, '\n')
        writer.writerow(v)

If you don't have all the values you want to write at once, us the same pattern:


with open("a_data.csv", 'w') as csvfile:
    writer = csv.DictWriter(csvfile, fieldnames = my_dict["a"].keys())
    while True:
        measurements = do_measurement()
        writer.writerow(measurements)

There is not need for my_dict.

Upvotes: 2

Related Questions