使用Python读取格式化文本

7 投票
2 回答
1968 浏览
提问于 2025-04-17 12:30

我想用Python来读取和写入以下格式的文件:

#h -F, field1 field2 field3
a,b,c
d,e,f
# some comments
g,h,i

这个文件的格式和普通的CSV文件很像,但有以下几点不同:

  1. 文件的第一行以#h开头
  2. 第一行的第二个元素是一个标签,用来表示分隔符
  3. 第一行剩下的部分是字段名称(这些名称之间总是用一个空格分开)
  4. 注释行总是以#开头,可以分散在文件的任何地方

有没有办法使用csv.DictReader()和csv.DictWriter()来读取和写入这些文件呢?

2 个回答

0

假设你已经打开了一个输入文件,叫做 input。首先,我们要读取文件的头部信息:

header = input.readline()

接下来,从头部信息中找出分隔符和字段名称,然后用这些信息来创建一个 DictReader。现在,不要直接用 input,而是给这个读取器输入一个表达式:

(ln for ln in input where ln[0] != '#')

这样就可以跳过注释部分了。

8

你可以单独解析第一行来找到分隔符和字段名:

    firstline = next(f).split()
    delimiter = firstline[1][-1]
    fields = firstline[2:]

注意,csv.DictReader可以接受任何可迭代的对象作为它的第一个参数。所以为了跳过注释,你可以把f放进一个迭代器(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

在你提供的数据上,这样做的结果是:

{'field2': 'b', 'field3': 'c', 'field1': 'a'}
{'field2': 'e', 'field3': 'f', 'field1': 'd'}
{'field2': 'h', 'field3': 'i', 'field1': 'g'}

要以这种格式写入文件,你可以使用一个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')

注意,你可以通过g.write(用于写入头部或注释行)或writer.writerow(用于写入csv数据)来写入output.csv

撰写回答