简体   繁体   中英

How to save a dictionary to a csv where each key has a different row

import time
import csv

def file_reader():
    product_location = {}
    location = 0
    with open('stockfile.csv', mode='r+') as f:
        reader = csv.reader(f)
        #next(reader) Can be included if I have headers to skip it
        products = {rows[0]: (rows[1],rows[2],rows[3],rows[4],rows[5]) for rows in reader}
        global products
    with open('stockfile.csv', mode='r+') as f:
        for line in f:
            lines = line
            print(lines)
            product_location[line.split(',')[0]] = location
            global product_location
        f.close()    

    total=0
    with open('stockfile.csv','r+') as f:
        for line in f:
            product_location[line.split(',')[0]] = location
            location += len(line)
total = 0
while True:
    file_reader()
    GTIN = input("\nPlease input GTIN or press [ENTER] to quit:\n")
    if GTIN == "":
        break
    if(GTIN not in products):
        print("Sorry your code was invalid, try again:")
        continue

    row = products[GTIN]
    description = row[0]
    value = row[1]
    stock = row[2]
    additional_stock = row[3]
    target_stock = row[4]

    print("Updating stock levels back to target level")
    stock = int(stock) + int(additional_stock)

    print('GTIN: ', GTIN)
    print('You have selected: ', description)
    print('The price of this product is: ', value)
    print('Stock: ', stock)

    quantity = input("Please input the quantity required: ")
    new_stock = int(stock) - int(quantity)

    if int(quantity) > int(stock):
        print("Sorry we don't have enough in stock please order again")
        print("Please try a different product or a smaller quantity: ")
        continue
    else:
        new_stock = int(stock) - int(quantity)
    if int(new_stock) < int(target_stock):
        answer = input("The stock is below target, if you would like to top up the product to the target stock level press [ENTER]")
        if answer == "":
            required = int(target_stock) - int(new_stock)
            added_stock = input("This is the target stock: %s, you must enter a minimum of %s" % (target_stock,required))
            stock= int(new_stock)+int(added_stock)
            while int(stock) < int(target_stock):
                print("Sorry input more please:")
                continue
            if int(stock) > int(target_stock):
                additional_stock = 0
                products[GTIN] = row[0],row[1],str(stock),str(additional_stock),row[4]
                print(products[GTIN])
                print(products)
                writer = csv.writer(open('stockfile.csv','w',newline=''))
                for key, row in products.items():
                    writer.writerow([key, value])

    else:
        additional_stock = int(target_stock) - int(new_stock)
        #I need to do the same here and change the dictionary and then send it to the CSV

        product_total = (int(quantity) * int(value))
    total = total + product_total
print('Total of the order is £%s' % total)

I am unable to work out how to send the dictionary back to the csv with this format (this is the format it is in when it has been called upon at the start and I want to send the information back in the same way). This is what the stockfile looks like: This is the format I want the dictionary to be sent back in as well as when it is opened . Please post the code as well which works and thanks in advance.

I think your error may be in your "writer.writerow" line and possibly some confusion between dictionary keys/values.

Every "writerow" should be writing a single 1-Dimensional List in every row. What you define as a "row" in the line :

    for key, row in products.items():

That is actually the value of the dictionary key . Yes, the data type of that value happens to be a list ( or a row ), but that list is the value that the dictionary key is pointing to.

Your code is not trying to write one single list row at a time. It is actually trying to write a Nested List to each Row in your visual spreadsheet. This is because the Value of your Dictionary Key is a List object in-itself which puts a list inside another writerow list.

    [ KeyName  ,  ValueObject  ]

Since our ValueObject is a List, we have a list inside a list.

Using your sample stockfile, this is how each row would look like in the spreadsheet as interpreted by most python file readers :

    [ KeyName  ,  [ List, Of, Row, Values ] ]

That's Nested List with 2 Dimensions. Only 2 Spreadsheet Cells would be written to in one row. The way to fix this is to make sure that "writer.writerow" is only writing a single 1-Dimensional List at a time.

An easy way to accomplish this is to concatenate 2 separate lists into 1 single list for the row.

However, since you are labeling the value as a "row" and one of the row items as "value", if we stick to your context, we should be able to concatenate that row value ( which is a list ) with the key name associated with it.

    for key, row in products.items():
        writer.writerow (  [ key ]  +  row  )

Since your "row" value variable in this case is already a list, we can simply read the dictionary key as its own list object to concatenate easily in one list ( and 1 line).

So then writerow is only writing 1 list at a time and each item in that list is placed in its own chronological cell in your csv file.

According to the specification in your comment:

mydict = {'23456789': ('TV', '2000', '22', '0', '20'), '12345678': ('Fridge', '1000', '24', '0', '20'), '34567890': ('DVD', '10', '23', '0', '20')}

with open("out.csv", "w") as f:
    for key in mydict:
        f.write(key + "," + ",".join(mydict[key]))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM