【问题标题】:change/writing single value to csv file python将单个值更改/写入到 csv 文件 python
【发布时间】:2014-04-09 15:30:18
【问题描述】:

我的代码有错误:

_csv.Error: sequence expected

我相信这是因为我试图只写一个值而不是列表等。

 exRtFile = open ('exchangeRate.csv')
    exchReader = csv.reader(exRtFile)
    exchWriter = csv.writer(exRtFile)
    loop2=0
    while loop2==0:
        selected=int(input("Please select an option: "))
        if selected == 1:
            change = input("What rate would you like to change: ")
            changeRt = float(input("What would you like to change the rate to: "))
            for row in exchReader:
                currency = row[0]
                if currency == change:
                    crntRt = row[1]
                    crntRt = changeRt
                    exchWriter.writerow(crntRt)
                    exRtFile.close()

解决此问题的最佳方法是什么,或者有更好的方法来更改 CSV 文件中的值?

csv 文件:

Pound Sterling,1
Euro,1.22
US Dollar,1.67
Japanese Yen,169.948

【问题讨论】:

  • 我没有测试过这个(这就是为什么它是一个评论)但我很确定你是对的。您可能想要更改整个 row 之类的 row[1]=changeRt,然后用更正的值写入洞 row
  • 问题在于每一行都有不同的值,如下所示:
  • 英镑 1 欧元 1.22 美元 1.67 日元 169.948
  • 您能否将exchangeRate.csv 文件的几行开头添加到问题中?
  • 刚刚完成,就是整个文件

标签: python csv python-3.x export-to-csv


【解决方案1】:

这是一些未经测试的代码,可以满足您的需求。这个想法是将文本读入内存,应用更新,然后在原始文件上写出结果。

您可以进一步增强询问用户是否要保存更改和添加新货币的功能,而不仅仅是告诉用户他们不知道。

在现实世界中,我会将这段代码分成三个独立的函数(甚至是类),一个用于读取,一个用于写入,一个用于编辑列表。

import csv

rates = {}

# read file into dictionary
with open('csv_file.csv', 'r') as in_file:
     rdr = csv.reader(in_file)
     for item in reader:
          rates[row[0]] = row[1]

# ask user for updates and apply to dictionary
while true:
     cmd = raw_input('Enter exchange rate to adjust, or blank to exit')
     if cmd is None or cmd.strip() == '':
        break
     if rates.has_key(cmd):
        new_rate = float(raw_input('Enter new exchange rate:'))
        rates[cmd] = new_rate
     else:
        print 'Currency {} is not known.'.format(cmd)

# Write the updated dictionary back over the same file.
with open('csv_file.csv', 'w') as out_file:
     wrtr = csv_writer(out_file)
     wrtr.writerows(rates)

【讨论】:

  • 你为什么要把它分成3个功能,有什么好处?
  • 这个程序中有三个不同的功能单元,阅读器、编写器和主代码。但是,像这样写在单个函数中,我没有机会命名功能单元。将它们放入函数中将允许我(并强迫我)这样做。此外,在现实世界的示例中,阅读器中可能会有更多的逻辑(至少)——错误检查、异常类等——我希望将其隔离在单独的 RateReader() 类中。
  • 这不起作用,我得到这样的输出 J,a,p,a,n,e,s,e, ,Y,e,n U,S, ,D,o, l,l,a,r P,o,u,n,d, ,S,t,e,r,l,i,n,g E,u,r,o
  • 在最后一行尝试wrtr.writerows(rates.items())。看起来你只是在写字典键。
【解决方案2】:

回答你的问题:是的,问题是你试图只写一个值,而writerow 需要一个列表。

也就是说……您会考虑稍微改变一下您的代码的工作方式吗?

这是我所做的(我现在已经测试过了,所以我知道它有效):

  • 首先,要求用户进行所有更改并将其保存在 dict 中,其中键是货币名称(例如欧元),值是新的货币值 ( 5.0,例如)用户可以按0 退出循环
  • 其次,逐行打开并读取您的exchangeRate.csv 文件。如果row[0](货币名称)是要更改的值之一,则在该行中更改它。
  • 无论发生什么(无论该行是否需要更改)都将该行写入一个新的临时文件exchangeRate.csv.tmp
  • 读取原始文件中的所有行后,您将拥有exchangeRate.csv.tmp,其中一些行未更改,一些行已更改。将.tmp 文件交换(移动)到exchangeRate.csv

不知道……可能变化太大了?反正就是这样:

import csv
import shutil

change_rates = {}
selected = 1
while selected:
    selected=int(raw_input("Please select an option: (1 to change, 0 to exit)"))
    if selected == 1:
        change = raw_input("What rate would you like to change?: ")
        changeRt = float(raw_input("What would you like to change the rate to: "))
        change_rates[change] =  changeRt

if len(change_rates) > 0:
    with open('exchangeRate.csv', 'r') as f_in,\
        open('exchangeRate.csv.tmp', 'w') as f_out:
        exchReader = csv.reader(f_in)
        exchWriter = csv.writer(f_out)
        for row in exchReader:
            if row[0] in change_rates:
                row[1] = change_rates[row[0]]
            exchWriter.writerow(row)
    shutil.move('exchangeRate.csv.tmp', 'exchangeRate.csv')

下面是一个示例执行:

Please select an option: (1 to change, 0 to exit)1
What rate would you like to change?: Euro
What would you like to change the rate to: 5
Please select an option: (1 to change, 0 to exit)0

borrajax@borrajax:~/Documents/Tests$ cat ./exchangeRate.csv 
Pound Sterling,1
Euro,5.0
US Dollar,1.67
Japanese Yen,169.948 

您始终可以进行更多优化,例如...允许不区分大小写的搜索,或检查货币是否实际已更改(即使用户说他想更改货币欧元5.0,如果那是欧元的汇率,那就不要做任何事情)......类似的事情。

编辑 1

我刚刚看过 Larry Lustig 的 answer,我同意对于小文件,因为它似乎是您的情况(您可以完全加载到内存中的文件),从我发布的磁盘连续读取和写入并不是最佳的。他将所有内容保存在内存中然后对同一个exchangeRate.csv 文件进行批量写入的想法可能更适合您的需求。

编辑 2

在对此答案的评论中回答您的问题:

  • .tmp 在结尾做了什么:exchangeRate.csv.tmp:

    这只是一个新名字。我添加了后缀 .tmp 以避免与您的原始文件 (exchangeRate.csv) 发生命名冲突。不过,你可以随意命名它(甚至是foobar.baz

  • 变量中'change'的目的是什么:change_rates[change] = changeRt:

    change 是一个包含要更改的货币名称的变量(在我发布的使用示例中,change 包含字符串 "Euro",因为这是用户(erm...我)输入的内容控制台。只是访问dict 的一种方式。

  • '[row[0]]' in: row1=change_rates[row[0]] 的目的是什么。

    我们同意在读取文件时,row[0](就像那样,不是[row[0]])包含文件中货币的名称(欧元、英镑...等等)对?所以在执行的某个时刻row[0] 将包含字符串"Euro",它(在我的测试示例中)是用户想要更改的货币。该字符串 ("Euro") 也是 change_rates 字典中的一个键(因为用户说他想更改它)所以您正在使用 keyvalue /strong> "Euro"change_rates 字典中(它会给你5.0)。几乎在做change_rates["Euro"] 为了更清楚地看到它,在if len(change_rates) > 0: 正上方的行中添加行print "Currencies to change: %s" % change_rates(这将向您展示字典的外观)

  • shutil.move('exchangeRate.csv.tmp', 'exchangeRate.csv') 是做什么的?

    它将包含新货币的文件复制到exchangeRate.csv(参见shutil documentation

【讨论】:

  • 看起来很棒,正是我想要的。只是有几个问题。 .tmp 在末尾做什么:exchangeRate.csv.tmp。变量中“更改”的目的是什么:change_rates [change] = changeRt。 '[row[0]]' 的目的是什么:row[1]=change_rates[row[0]]。 shutil.move('exchangeRate.csv.tmp', 'exchangeRate.csv') 是做什么的?
  • Dangit...我忘了回答你的问题...查看我最新的最新编辑! :D :D
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多