在Python中更改/写入CSV文件的单个值

0 投票
2 回答
4303 浏览
提问于 2025-04-18 02:03

我的代码出错了:

_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

2 个回答

1

回答你的问题:是的,问题在于你试图只写一个值,而 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 的 回答,我同意,对于像你这种小文件(可以完全加载到内存中的文件),我之前提到的持续从磁盘读取和写入并不是最优的。他的想法是将所有内容保存在内存中,然后一次性写入同一个 exchangeRate.csv 文件,可能更符合你的需求。

编辑 2

为了回答你在这条回答下的评论中的问题:

  • exchangeRate.csv.tmp 末尾的 .tmp 是什么?

    这只是一个新名称。我加上 .tmp 后缀是为了避免与原始文件(exchangeRate.csv)发生命名冲突。不过你可以随便命名(甚至可以叫 foobar.baz)。

  • 变量中的 'change' 在 change_rates[change] = changeRt 中有什么作用?

    change 是一个变量,里面包含了要更改的货币名称(在我给出的示例中,change 包含字符串 "Euro",因为那是用户(呃……我)在控制台输入的内容)。这只是访问 字典 的一种方式。

  • 在 row1=change_rates[row[0]] 中 '[row[0]]' 的目的是什么?

    我们已经同意,在读取文件时,row[0](就这样,不是 [row[0]])包含了文件中货币的名称(欧元、英镑……等等),对吧?所以在执行的某个时刻,row[0] 将包含字符串 "Euro",这(在我的测试示例中)是用户想要更改的货币。这个字符串("Euro")也是 change_rates 字典中的一个键(因为用户说他想更改它),所以你在查询 change_rates 字典中键为 "Euro" 的项的(这将给你 5.0)。这实际上就是在做 change_rates["Euro"]。为了更清楚一点,可以在 if len(change_rates) > 0: 之前加上这一行 print "要更改的货币: %s" % change_rates(这将显示字典的样子)。

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

    它将新货币的文件复制到 exchangeRate.csv(见 shutil 文档)。

2

这里有一些代码,虽然没有测试过,但可以实现你想要的功能。这个思路是先把文本读到内存中,进行更新,然后把结果写回原来的文件。

你还可以进一步改进,比如问用户是否想保存他们的更改,或者让他们添加新的货币,而不是直接告诉用户这些货币是未知的。

在实际应用中,我会把这段代码分成三个独立的部分(或者甚至是类),一个负责读取,一个负责写入,还有一个负责编辑列表。

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)

撰写回答