问题现象
使用 csv 遍历器遍历文件:
with open(DATA_PATH, "r", encoding="UTF-8") as file:
csv_row: dict
for csv_row in csv.DictReader(file):
......
遍历时,出现报错如下:
_csv.error: line contains nul
问题原因
这是因为在文件中存在特殊符号 nul,即 ASCII 值为 0 的字符,可以表示为 \x00
(ASCII 值为 0 的字符)或 \u0000
(Unicode 码值为 0 的字符)。
解决方案
对于这种情况,我们有如下选择:
- 方案一:新增一个行迭代器,并对原始数据进行过滤
- 方案二:使用 pandas 的
read_csv
函数,pandas 兼容了\x00
字符的情况(需要使用 pandas 进行编辑,如果原本不需要 pandas 可能较为麻烦) - 方案三:读取整个文件进行替换后,再调用 csv 遍历器(这会导致整个文件存储于内存中,如果文件很大则不可行)
下面我们来说方案一的具体实现方法:
Step 1|新增过滤旧行迭代器中包含的 \x00
字符的生成器。
其中 file
为打开的文件对象,每次遍历会迭代中其中的一行,将这一行中的 \x00
替换为空回再生成出去。这样,我们仍然不需要将整个文件存储在内存中,在使用上与直接遍历 file
区别不大。
def filter_file(file):
for row in file:
row = row.replace("\x00", "")
yield row
Step 2|将 csv.DictReader(file)
中的参数由 file
改为 filter_file(file)
。
with open(DATA_PATH, "r", encoding="UTF-8") as file:
csv_row: dict
for csv_row in csv.DictReader(filter_file(file)):
......