你能跳过 python csv 中的非 utf-8 数据吗?

Can you skip non utf-8 data in python csv?

我正在处理 python 中的一个非常大的 csv 文件,其中一些行抛出错误“'utf-8' 编解码器无法解码位置 7657 中的字节 0x9b:起始字节无效”。有没有一种方法可以跳过非 utf-8 的行而无需手动删除或修复数据?

for filename in filenames:
f = open(filename, 'rt')
reader = csv.reader(f, delimiter = ',')
for row in reader:
    #process data for future use

我无法使用非 utf8 数据,因为后面的过程需要使用 utf-8

您可以使用过滤器将一行读取为原始字节,尝试将其转换为 unicode 作为 UTF8,然后:

  • 如果成功,将其传递给 csv reader
  • 如果没有,存储起来供以后分析

假设您使用的是 Python2,您可以使用类似的东西:

class MyFilter:
    def __init__(self, instr, errstr):
        self.instr = instr
        self.errstr = errstr
    def __enter__(self):
        print("ENTERING filter")
        return self
    def __exit__(self, a, b, c):
        print("EXITING filter")
        self.instr.close()
        self.errstr.close()
        return False
    def __next__(self):
        line = next(self.instr)
        while True:
            try:
                t = line.decode('utf8')
                return line.strip()
            except UnicodeDecodeError:
                self.errstr.write(line)
                line = next(self.instr)
        return line
    def __iter__(self):
        return self
    def next(self):
        return self.__next__()

然后您可以那样使用它(假设 Python 2.7),在 err.txt 中获取所有违规行:

with open('file.csv') as istream, open("err.txt", 'w') as err, MyFilter(istream, err) as fd:
    c = csv.reader(fd)
    for i in c:
        # do you stuff, eg: print i

如果您使用 Python 3,您可以使用几乎相同的过滤器 class,只需将行 return line.strip() 替换为 return t.strip(),以便 return字符串而不是字节。

用法又几乎相同:

with open('file.csv', 'rb') as istream, open("err.txt", 'wb') as err, MyFilter(istream, err) as fd:
    c = csv.reader(fd)
    for i in c:
        # do you stuff, eg: print (i)

根据您的评论,您还想过滤包含空字符的行。这只需要稍微改变过滤器,while 块变成 (Python 3 version) :

    while True:
        if b'\x00' not in line:
            try:
                t = line.decode('utf8')
                return t.strip()
            except UnicodeDecodeError:
                pass
        self.errstr.write(line)
        line = next(self.instr)