我正在尝试使用以下格式的文件:
# Comments
# More comments
1,foo,bar,1
1,foo,bar,2
21,foo,bar,8
end_of_file
并将其处理为如下列表:
listing = [[1,'foo','bar',1], [1,'foo','bar',2], [21,'foo','bar',8]]
目前,我正在运行类似于:
的内容listing = []
with open('foo_file.cfg','r') as f:
for line in f:
if line[0].isDigit:
listing.append(line) # i've also tried listing.append([line])
显然,我最终会:
[['1,foo,bar,1'],['1,foo,bar,2'],['21,foo,bar,8']]
我知道我可以用逗号分割line
,重建一个新列表,然后将列表附加到listing.
如果这是正确的方法,我绝对愿意这样做,但我认为他们的可能会更清洁。我知道csv
模块会将整个文件读成适当的格式,但我不确定如何处理选择性删除某些数据,例如注释。
答案 0 :(得分:2)
这是使用csv
模块的一种方法,它避免明确地计算一些重复性任务(逗号分隔符,换行符等)。
from io import StringIO
import csv
mystr = StringIO("""1,foo,bar,1
1,foo,bar,2
21,foo,bar,8""")
res = []
# replace mystr with open('file.csv', 'r')
with mystr as f:
reader = filter(None, csv.reader(f)) # ignore empty lines
for line in reader:
if line[0].isdigit():
res.append([int(line[0]), line[1], line[2], int(line[3])])
print(res)
[[1, 'foo', 'bar', 1],
[1, 'foo', 'bar', 2],
[21, 'foo', 'bar', 8]]
答案 1 :(得分:1)
您可以在没有任何模块的情况下以类似方式执行此操作:
lst = []
for line in f:
if not line.startswith('#') and line:
lst.append([int(i) if i.isdigit() else i for i in line.split(',')])
print(lst)
# [[1, 'foo', 'bar', 1], [1, 'foo', 'bar', 2], [21, 'foo', 'bar', 8]]
答案 2 :(得分:1)
如果最后一行是您想摆脱的唯一一行,可以使用pandas.read_csv
属性或error_bad_lines=False
skipfooter=1
如果有必要遍历文件的行并检查要导入的行,那么我只需将您追加到listing
列表的行更改为
listing.append(line.split(','))
答案 3 :(得分:1)
一种Pythonic方法是使用itertools.dropwhile()
忽略满足特定条件的第一行。由于csv.reader
对象是迭代器,因此不再需要读取整个文件一次,然后再次循环遍历这些行以将其过滤掉。您也可以通过检查行的验证(not(x)
函数中的lambda
来删除空行。)
import csv
from itertools import dropwhile
with open('test.csv') as f:
reader = dropwhile(lambda x: not(x) or x[0].startswith('#'), csv.reader(f))
# print(list(reader))
# [['1', 'foo', 'bar', '1'], ['1', 'foo', 'bar', '2'], ['21', 'foo', 'bar', '8']]