使用python读取格式化文本

Dav*_*ave 6 python csv

我想使用以下格式的python读写文件:

#h -F, field1 field2 field3
a,b,c
d,e,f
# some comments
g,h,i
Run Code Online (Sandbox Code Playgroud)

此文件非常类似于典型的CSV,但以下情况除外:

  1. 标题行以#h开头
  2. 标题行的第二个元素是用于表示分隔符的标记
  3. 标题的其余元素是字段名称(始终用单个空格分隔)
  4. 注释行始终以#开头,可以分散在整个文件中

有什么办法可以使用csv.DictReader()和csv.DictWriter()来读写这些文件吗?

unu*_*tbu 8

您可以分别解析第一行以查找分隔符和字段名:

    firstline = next(f).split()
    delimiter = firstline[1][-1]
    fields = firstline[2:]
Run Code Online (Sandbox Code Playgroud)

请注意,csv.DictReader可以将任何iterable作为其第一个参数.因此,要跳过注释,可以包含f一个iterator(skip_comments),它只产生非注释行:

import csv
def skip_comments(iterable):
    for line in iterable:
        if not line.startswith('#'):
            yield line

with open('data.csv','rb') as f:
    firstline = next(f).split()
    delimiter = firstline[1][-1]
    fields = firstline[2:]
    for line in csv.DictReader(skip_comments(f),
                               delimiter = delimiter, fieldnames = fields):
        print line
Run Code Online (Sandbox Code Playgroud)

在您发布的数据上,这会产生

{'field2': 'b', 'field3': 'c', 'field1': 'a'}
{'field2': 'e', 'field3': 'f', 'field1': 'd'}
{'field2': 'h', 'field3': 'i', 'field1': 'g'}
Run Code Online (Sandbox Code Playgroud)

要以这种格式编写文件,您可以使用header辅助函数:

def header(delimiter,fields):
    return '#h -F{d} {f}\n'.format(d = delimiter, f=' '.join(fields))

with open('data.csv', 'rb') as f:
    with open('output.csv', 'wb') as g:
        firstline = next(f).split()
        delimiter = firstline[1][-1]
        fields = firstline[2:]
        writer = csv.DictWriter(g, delimiter = delimiter, fieldnames = fields)
        g.write(header(delimiter,fields))
        for row in csv.DictReader(skip_comments(f),
                                   delimiter = delimiter, fieldnames = fields):
            writer.writerow(row)
            g.write('# comment\n')
Run Code Online (Sandbox Code Playgroud)

请注意,您可以写入(output.csv使用g.write标题或注释行)或writer.writerow(对于csv).