【问题标题】:How do I correctly write a CSV file on individual rows and columns?如何在单个行和列上正确写入 CSV 文件?
【发布时间】:2015-05-04 04:03:18
【问题描述】:

我正在用 Python 制作一个小型食谱输入和输出程序,但是我在将配料写入 CSV 文件时遇到了麻烦。我正在尝试使用以下代码将列表的每个项目打印到逗号分隔的文件中:

with open('recipes/' + recipeName + '.csv', 'w') as csvfile:
    recipewriter = csv.writer(csvfile)
    recipewriter.write(ingredientList[0])
    recipewriter.write(ingredientList[1])
    recipewriter.write(ingredientList[2])

在列表中,共有三个项目。例如,这可能是我要保存到文件的列表:

ingredientList = ['flour', '500', 'g']

我希望数据在 CSV 文件中显示如下:

flour,
500,
g,

相反,它看起来像这样:

f,l,o,u,r,
5,0,0,
g,

如何让它以我想要的格式显示?

这是我的源代码:

#Python 3.3.3

import sys #Allows use of the 'exit()' function
import csv #Allows use of the CSV File API

def mainMenu():
    print("########################################################")
    print("# Welcome to the recipe book, please select an option: #")
    print("# 1. Add new recipe                                    #")
    print("# 2. Lookup existing recipe                            #")
    print("# 3. Exit                                              #")
    print("########################################################")

    selectedOption = None
    inputtedOption = input()

    try:
        inputtedOption = int(inputtedOption)
    except ValueError:
        print("Invalid option entered")

    if inputtedOption == 1:
        selectedOption = inputtedOption
    elif inputtedOption == 2:
        selectedOption = inputtedOption
    elif inputtedOption == 3:
        print("Exiting...")
        sys.exit(0)

    return selectedOption

def validateInput(inputtedData):
    try: #Test if data is an integer greater than 1
        inputtedData = int(inputtedData)
        if int(inputtedData) < 1: #Recipes cannot contain less than 1 ingredient
            print("Sorry, invalid data entered.\n('%s' is not valid for this value - positive integers only)" % inputtedData)
            return False
        return int(inputtedData)
    except ValueError:
        print("Sorry, invalid data entered.\n('%s' is not valid for this value - whole integers only [ValueError])\n" % inputtedData)
        return False

def addRecipe():
    print("Welcome to recipe creator! The following questions will guide you through the recipe creation process.\nPlease enter the name of your recipe (e.g. 'Pizza'):")
    recipeName = input()
    print("Recipe Name: %s" % recipeName)
    print("Please enter the amount of people this recipe serves (e.g. '6'):")
    recipeServingAmount = input()
    if validateInput(recipeServingAmount) == False:
        return
    else:
        recipeServingAmount = validateInput(recipeServingAmount)
    print("Recipe serves: %s" % recipeServingAmount)
    print("Please enter the number of ingredients in this recipe (e.g. '10'):")
    recipeNumberOfIngredients = input()
    if validateInput(recipeNumberOfIngredients) == False:
        return
    else:
        recipeNumberOfIngredients = validateInput(recipeNumberOfIngredients)
    print("Recipe contains: %s different ingredients" % recipeNumberOfIngredients)
    ingredientList = {}
    i = 1
    while i <= recipeNumberOfIngredients:
        nthFormat = "st"
        if i == 2:
            nthFormat = "nd"
        elif i == 3:
            nthFormat = "rd"
        elif i >= 4:
            nthFormat = "th"
        ingredientNumber = str(i) + nthFormat
        print("Please enter the name of the %s ingredient:" % ingredientNumber)
        ingredientName = input()
        print("Please enter the quantity of the %s ingredient:" % ingredientNumber)
        ingredientQuantity = input()
        print("Please enter the measurement value for the %s ingredient (leave blank for no measurement - e.g. eggs):"  % ingredientNumber)
        ingredientMeasurement = input()
        print("%s ingredient: %s%s %s" % (ingredientNumber, ingredientQuantity, ingredientMeasurement, ingredientName))
        finalIngredient = [ingredientName, ingredientQuantity, ingredientMeasurement]
        print(finalIngredient[1])
        ingredientList[i] = finalIngredient
        with open('recipes/' + recipeName + '.csv', 'w') as csvfile:
            recipewriter = csv.writer(csvfile)
            recipewriter.write(ingredientList[0])
            recipewriter.write(ingredientList[1])
            recipewriter.write(ingredientList[2])

        i = i + 1

def lookupRecipe():
    pass  # To-do: add CSV reader and string formatter

#Main flow of program
while True:
    option = mainMenu()

    if option == 1:
        addRecipe()
    elif option == 2:
        lookupRecipe()

【问题讨论】:

  • 虽然您可以生成一个包含"flour,\n500,\ng,\n" 的文本文件(几个答案显示如何),但请注意这是糟糕的 CSV 结构。相关数据分散在几行中,结尾的逗号表示(缺少)第二列。

标签: python csv python-3.x io


【解决方案1】:

最简单的方法是在列表上调用 join 添加一个 , 和一个换行符,然后忘记使用 csv 模块:

with open('recipes/{}.csv'.format(recipeName), 'w') as csvfile:
        csvfile.write(",\n".join(ingredientList))

输出:

flour,
500,
g

我猜你实际上是在使用writerow not write 因为csv.writer 没有 write 方法。

您看到 f,l,o,u,r, 的原因是因为 csv.writer.writerow 需要一个可迭代的,因此当您传递字符串时,它会迭代并单独写入每个字符。

您需要使用recipewriter.writerow([ingredientList[0]]),将字符串包装在一个列表中。

这实际上仍然不会在字符串末尾添加任何尾随逗号。

如果您想在包括最后一行在内的每一行后面加上逗号:

with open('recipes/{}.csv'.format("foo"), 'w') as csvfile:
    for ele in ingredientList:
         csvfile.write("{},\n".format(ele))

输出:

flour,
500,
g,

如果您想要一个有用的 csv,您最好将每个列都设为自己的列,或者将每个列写入自己的行:

import csv
with open('{}.csv'.format("foo"), 'w') as csvfile:
    recipewriter = csv.writer(csvfile)
    recipewriter.writerow(ingredientList)

输出:

flour,500,g

或者在没有尾随逗号的单独行上:

with open('{}.csv'.format("foo"), 'w') as csvfile:
    recipewriter = csv.writer(csvfile)
    for ele in ingredientList:
         recipewriter.writerow([ele])

输出:

flour
500
g

【讨论】:

    【解决方案2】:

    csv.writers 没有write() 方法。在 Python 3 中,您可以这样做:

    with open('recipes/' + recipeName + '.csv', 'w', newline='') as csvfile:
        recipewriter = csv.writer(csvfile)
        recipewriter.writerow([ingredientList[0]])
        recipewriter.writerow([ingredientList[1]])
        recipewriter.writerow([ingredientList[2]])
    

    【讨论】:

    • 当我尝试这段代码时,我似乎得到了 KeyError: 0
    • 这意味着 字典 ingredientList 中没有您尝试访问的三个键之一的条目 — 01 , 或 2 — 取决于 KeyError 出现在哪一行 writerow() 上。在那之前你可以试试print(ingredientList),看看里面到底有什么(也许还有为什么它不是你所期望的)。
    • 正如我所提到的,在您的实际代码中,ingredientList 是字典而不是列表。 KeyError 是因为您从未在 ingredientList[0] 中放入任何内容,因为您在 while 循环之前初始化了 i = 1。解决此问题的一种方法是使用ingredientList[1][2][3]。我注意到的另一个问题是,您每次都在通过循环重写整个文件——因此,例如,如果配方中有 4 种不同的成分,则只有最后一种会出现在文件中。因此,我会将文件的打开和csv.writer 的创建移出while 循环。
    猜你喜欢
    • 2012-05-28
    • 2018-02-18
    • 1970-01-01
    • 1970-01-01
    • 2018-06-01
    • 2018-02-04
    • 2018-06-03
    • 1970-01-01
    • 2020-11-08
    相关资源
    最近更新 更多