为 csv.reader 预处理一行

Nin*_*oor 1 python csv

我正在尝试使用 csv.reader 解析 csv 文件。但是,此文件中的字段之一未正确编码。它是一个用双引号括起来的字符串,但字符串中的双引号不会被转义。

id,name,score
1,"something" like this",20
Run Code Online (Sandbox Code Playgroud)

由于只有一个这样的字段,我应该能够通过查找第一个和最后一个双引号并转义它们之间的任何双引号来更正该字段。有什么方法可以在 csv.reader 处理一行之前对其进行预处理以实现这样的目标?

PM *_*ing 5

csv.reader会很乐意从可迭代的读取线,包括发电机,所以我们可以使用一个发电机做报价逃逸。但是我们还需要说明csv.reader我们的escapechar

我已将一些测试数据作为字符串列表嵌入到此代码中,但您可以将打开的文件传递给fixlines生成器。

import csv 

data = '''\
id,name,score
1,"something" like this",20
2,"another thing" like that",30
'''.splitlines()

def fixlines(lines):
    for row in lines:
        try:
            first = row.index('"') + 1
            last = row.rindex('"')
        except ValueError:
            pass
        else:
            stuff = row[first:last].replace('"', '\\"')
            row = row[:first] + stuff + row[last:]
        yield row

reader = csv.reader(fixlines(data), escapechar='\\')
for row in reader:
    print(row)
Run Code Online (Sandbox Code Playgroud)

输出

['id', 'name', 'score']
['1', 'something" like this', '20']
['2', 'another thing" like that', '30']
Run Code Online (Sandbox Code Playgroud)

此代码不会更改不包含双引号(如标题行)或一对双引号的行,但如果它找到包含单个双引号的行,它可能不会完全按照您的要求执行。修复它留给读者作为练习。;)

但是,它确实正确处理了带引号的字符串中的逗号。


这也适用于csv.DictReader

reader = csv.DictReader(fixlines(data), escapechar='\\')
for row in reader:
    print(row)
Run Code Online (Sandbox Code Playgroud)

输出

OrderedDict([('id', '1'), ('name', 'something" like this'), ('score', '20')])
OrderedDict([('id', '2'), ('name', 'another thing" like that'), ('score', '30')])
Run Code Online (Sandbox Code Playgroud)