使用python中的csv模块写入特定单元格
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3699927/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Writing to a particular cell using csv module in python
提问by sagar
I have to write a value to a particular cell (say the 8th cell) in my csv file.
I can see there is a csvwriter.writerow(row)method to write an entire row, but I am not seeing anything to write a value to a particular cell.
我必须在我的 csv 文件中向特定单元格(比如第 8 个单元格)写入一个值。我可以看到有一种csvwriter.writerow(row)写入整行的方法,但我没有看到任何将值写入特定单元格的方法。
采纳答案by Tendayi Mawushe
The csv moduleprovides facilities to read and write csv files but does not allow the modification specific cells in-place.
该CSV模块提供了一些工具来读取和写入的CSV文件,但不允许修改特定的细胞原位。
Even the csvwriter.writerow(row)method you highlight in your question does not allow you to identify and overwrite a specific row. Rather it writes the rowparameter to the writer's file object, in effect it simply appends a row the csv file associated with the writer.
即使csvwriter.writerow(row)您在问题中突出显示的方法也不允许您识别和覆盖特定行。相反,它将row参数写入编写器的文件对象,实际上它只是在与编写器关联的 csv 文件中附加一行。
Do not be dissuaded from using the csv modulethough, it is simple to use and with the primitives provided you could implement the higher level functionality you are looking for relatively easily.
不过,不要劝阻使用csv 模块,它使用简单,并且提供的原语可以相对轻松地实现您正在寻找的更高级别的功能。
For example take a look at the following csv file:
例如,看看下面的 csv 文件:
1,2,3,four,5
1,2,3,four,5
1,2,3,four,5
The word fouris in column 3 (the fourth column but a row is just a list so the indexing is zero based), this can be easily updated to contain the digit 4with the following program:
这个词four在第 3 列(第四列但一行只是一个列表,所以索引是从零开始的),这可以很容易地更新为包含4以下程序的数字:
import csv
in_file = open("d:/in.csv", "rb")
reader = csv.reader(in_file)
out_file = open("d:/out.csv", "wb")
writer = csv.writer(out_file)
for row in reader:
row[3] = 4
writer.writerow(row)
in_file.close()
out_file.close()
Resulting in the output:
导致输出:
1,2,3,4,5
1,2,3,4,5
1,2,3,4,5
Granted creating some generic function that allows specific rows and columns to be identified and updated is a little more work, but not much more as manipulating a csv file in Python is just manipulating a sequence of lists.
当然,创建一些允许识别和更新特定行和列的通用函数需要更多的工作,但并不像在 Python 中操作 csv 文件只是操作一系列列表那样多。
回答by pyInTheSky
I agree, this is annoying. I wound up subclassing csv.DictReader. This allows for cell based lookup edit in place, and dump. I have the code posted on activestate: In place csv lookup, manipulation and export
我同意,这很烦人。我结束了对 csv.DictReader 的子类化。这允许在适当的位置进行基于单元格的查找编辑和转储。我在 activestate 上发布了代码: 就地 csv 查找、操作和导出
import csv, collections, copy
"""
# CSV TEST FILE 'test.csv'
TBLID,DATETIME,VAL
C1,01:01:2011:00:01:23,5
C2,01:01:2012:00:01:23,8
C3,01:01:2013:00:01:23,4
C4,01:01:2011:01:01:23,9
C5,01:01:2011:02:01:23,1
C6,01:01:2011:03:01:23,5
C7,01:01:2011:00:01:23,6
C8,01:01:2011:00:21:23,8
C9,01:01:2011:12:01:23,1
#usage (saving this cose as CustomDictReader.py)
>>> import CustomDictReader
>>> import pprint
>>> test = CustomDictReader.CSVRW()
>>> success, thedict = test.createCsvDict('TBLID',',',None,'test.csv')
>>> pprint.pprint(dict(thedict))
{'C1': OrderedDict([('TBLID', 'C1'), ('DATETIME', '01:01:2011:00:01:23'), ('VAL', '5')]),
'C2': OrderedDict([('TBLID', 'C2'), ('DATETIME', '01:01:2012:00:01:23'), ('VAL', '8')]),
'C3': OrderedDict([('TBLID', 'C3'), ('DATETIME', '01:01:2013:00:01:23'), ('VAL', '4')]),
'C4': OrderedDict([('TBLID', 'C4'), ('DATETIME', '01:01:2011:01:01:23'), ('VAL', '9')]),
'C5': OrderedDict([('TBLID', 'C5'), ('DATETIME', '01:01:2011:02:01:23'), ('VAL', '1')]),
'C6': OrderedDict([('TBLID', 'C6'), ('DATETIME', '01:01:2011:03:01:23'), ('VAL', '5')]),
'C7': OrderedDict([('TBLID', 'C7'), ('DATETIME', '01:01:2011:00:01:23'), ('VAL', '6')]),
'C8': OrderedDict([('TBLID', 'C8'), ('DATETIME', '01:01:2011:00:21:23'), ('VAL', '8')]),
'C9': OrderedDict([('TBLID', 'C9'), ('DATETIME', '01:01:2011:12:01:23'), ('VAL', '1')])}
>>> thedict.keys()
['C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9']
>>> thedict['C2']['VAL'] = "BOB"
>>> pprint.pprint(dict(thedict))
{'C1': OrderedDict([('TBLID', 'C1'), ('DATETIME', '01:01:2011:00:01:23'), ('VAL', '5')]),
'C2': OrderedDict([('TBLID', 'C2'), ('DATETIME', '01:01:2012:00:01:23'), ('VAL', 'BOB')]),
'C3': OrderedDict([('TBLID', 'C3'), ('DATETIME', '01:01:2013:00:01:23'), ('VAL', '4')]),
'C4': OrderedDict([('TBLID', 'C4'), ('DATETIME', '01:01:2011:01:01:23'), ('VAL', '9')]),
'C5': OrderedDict([('TBLID', 'C5'), ('DATETIME', '01:01:2011:02:01:23'), ('VAL', '1')]),
'C6': OrderedDict([('TBLID', 'C6'), ('DATETIME', '01:01:2011:03:01:23'), ('VAL', '5')]),
'C7': OrderedDict([('TBLID', 'C7'), ('DATETIME', '01:01:2011:00:01:23'), ('VAL', '6')]),
'C8': OrderedDict([('TBLID', 'C8'), ('DATETIME', '01:01:2011:00:21:23'), ('VAL', '8')]),
'C9': OrderedDict([('TBLID', 'C9'), ('DATETIME', '01:01:2011:12:01:23'), ('VAL', '1')])}
>>> test.updateCsvDict(thedict)
>>> test.createCsv('wb')
"""
class CustomDictReader(csv.DictReader):
"""
override the next() function and use an
ordered dict in order to preserve writing back
into the file
"""
def __init__(self, f, fieldnames = None, restkey = None, restval = None, dialect ="excel", *args, **kwds):
csv.DictReader.__init__(self, f, fieldnames = None, restkey = None, restval = None, dialect = "excel", *args, **kwds)
def next(self):
if self.line_num == 0:
# Used only for its side effect.
self.fieldnames
row = self.reader.next()
self.line_num = self.reader.line_num
# unlike the basic reader, we prefer not to return blanks,
# because we will typically wind up with a dict full of None
# values
while row == []:
row = self.reader.next()
d = collections.OrderedDict(zip(self.fieldnames, row))
lf = len(self.fieldnames)
lr = len(row)
if lf < lr:
d[self.restkey] = row[lf:]
elif lf > lr:
for key in self.fieldnames[lr:]:
d[key] = self.restval
return d
class CSVRW(object):
def __init__(self):
self.file_name = ""
self.csv_delim = ""
self.csv_dict = collections.OrderedDict()
def setCsvFileName(self, name):
"""
@brief stores csv file name
@param name- the file name
"""
self.file_name = name
def getCsvFileName(self):
"""
@brief getter
@return returns the file name
"""
return self.file_name
def getCsvDict(self):
"""
@brief getter
@return returns a deep copy of the csv as a dictionary
"""
return copy.deepcopy(self.csv_dict)
def clearCsvDict(self):
"""
@brief resets the dictionary
"""
self.csv_dict = collections.OrderedDict()
def updateCsvDict(self, newCsvDict):
"""
creates a deep copy of the dict passed in and
sets it to the member one
"""
self.csv_dict = copy.deepcopy(newCsvDict)
def createCsvDict(self,dictKey, delim, handle = None, name = None, readMode = 'rb', **kwargs):
"""
@brief create a dict from a csv file where:
the top level keys are the first line in the dict, overrideable w/ **kwargs
each row is a dict
each row can be accessed by the value stored in the column associated w/ dictKey
that is to say, if you want to index into your csv file based on the contents of the
third column, pass the name of that col in as 'dictKey'
@param dictKey - row key whose value will act as an index
@param delim - csv file deliminator
@param handle - file handle (leave as None if you wish to pass in a file name)
@param name - file name (leave as None if you wish to pass in a file handle)
@param readMode - 'r' || 'rb'
@param **kwargs - additional args allowed by the csv module
@return bool - SUCCESS|FAIL
"""
self.csv_delim = delim
try:
if isinstance(handle, file):
self.setCsvFileName(handle.name)
reader = CustomDictReader(handle, delim, **kwargs)
else:
if None == name:
name = self.getCsvFileName()
else:
self.setCsvFileName(name)
reader = CustomDictReader(open(name, readMode), delim, **kwargs)
for row in reader:
self.csv_dict[row[dictKey]] = row
return True, self.getCsvDict()
except IOError:
return False, 'Error opening file'
def createCsv(self, writeMode, outFileName = None, delim = None):
"""
@brief create a csv from self.csv_dict
@param writeMode - 'w' || 'wb'
@param outFileName - file name || file handle
@param delim - csv deliminator
@return none
"""
if None == outFileName:
outFileName = self.file_name
if None == delim:
delim = self.csv_delim
with open(outFileName, writeMode) as fout:
for key in self.csv_dict.values():
fout.write(delim.join(key.keys()) + '\n')
break
for key in self.csv_dict.values():
fout.write(delim.join(key.values()) + '\n')
回答by Roy learns to code
suppose you have a csv file called mylist.csv with following lines:
假设您有一个名为 mylist.csv 的 csv 文件,其中包含以下几行:
a, b, c, d
e, f, g, h
i, j, k, l
if you want to modify 'h' to become 'X', can use this code, need to import csv module:
如果要将'h'修改为'X',可以使用这段代码,需要导入csv模块:
f = open('mylist.csv', 'r')
reader = csv.reader(f)
mylist = list(reader)
f.close()
mylist[1][3] = 'X'
my_new_list = open('mylist.csv', 'w', newline = '')
csv_writer = csv.writer(my_new_list)
csv_writer.writerows(mylist)
my_new_list.close()
If you want to modify a particular column for each row, just add the for loop to iterate.
如果要为每一行修改特定列,只需添加 for 循环进行迭代。

