我的程序需要读取可能有1,2或3列的csv文件,并且需要相应地修改其行为。在迭代器运行之前,是否有一种简单的方法可以检查列数而不“消耗”一行?以下代码是我能管理的最优雅的代码,但我更愿意在for循环开始之前运行检查:
import csv
f = 'testfile.csv'
d = '\t'
reader = csv.reader(f,delimiter=d)
for row in reader:
if reader.line_num == 1: fields = len(row)
if len(row) != fields:
raise CSVError("Number of fields should be %s: %s" % (fields,str(row)))
if fields == 1:
pass
elif fields == 2:
pass
elif fields == 3:
pass
else:
raise CSVError("Too many columns in input file.")
修改:我应该包含有关我的数据的更多信息。如果只有一个字段,则必须包含科学记数法的名称。如果有两个字段,则第一个字段必须包含名称,第二个字段必须包含链接代码。如果有三个字段,则附加字段包含一个标志,该标志指定名称当前是否有效。因此,如果任何行包含1,2或3列,则所有列都必须具有相同的值。
答案 0 :(得分:22)
您可以使用itertools.tee
itertools.tee(iterable [,n = 2])
从a返回n个独立迭代器 单一可迭代。
例如
reader1, reader2 = itertools.tee(csv.reader(f, delimiter=d))
columns = len(next(reader1))
del reader1
for row in reader2:
...
请注意,完成后删除对reader1
的引用非常重要 - 否则tee
必须将所有行存储在内存中以防再次呼叫next(reader1)
答案 1 :(得分:11)
这似乎也有效:
import csv
datafilename = 'testfile.csv'
d = '\t'
f=open(datafilename,'r')
reader=csv.reader(f,delimiter=d)
ncol=len(next(reader)) # Read first line and count columns
f.seek(0) # go back to beginning of file
for row in reader:
pass #dostuff
答案 2 :(得分:4)
如果用户为您提供包含较少列的CSV文件,会发生什么?是否使用默认值?
如果是这样,为什么不用空值扩展行呢?
reader = csv.reader(f,delimiter=d)
for row in reader:
row += [None] * (3 - len(row))
try:
foo, bar, baz = row
except ValueError:
# Too many values to unpack: too many columns in the CSV
raise CSVError("Too many columns in input file.")
现在bar和baz将至少为None
,异常处理程序将处理超过3项的任何行。
答案 3 :(得分:1)
我建议这样一种简单的方法:
with open('./testfile.csv', 'r') as csv:
first_line = csv.readline()
your_data = csv.readlines()
ncol = first_line.count(',') + 1
答案 4 :(得分:-1)
我会按如下方式重建它(如果文件不是太大):
import csv
f = 'testfile.csv'
d = '\t'
reader = list(csv.reader(f,delimiter=d))
fields = len( reader[0] )
for row in reader:
if fields == 1:
pass
elif fields == 2:
pass
elif fields == 3:
pass
else:
raise CSVError("Too many columns in input file.")