你能跳过 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)
我正在处理 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)