大CSV随机分片后pandas读取小文件报EmptyDataError问题
大型CSV随机拆分后pandas读取报错问题
我需要处理无法一次性加载到内存的大型CSV文件,计划先通过csv.DictReader遍历文件,用csv.DictWriter将每行随机写入多个小CSV,再打乱合并。但第一步就卡壳:生成的小文件用pandas读取时抛出pandas.errors.EmptyDataError: No columns to parse from file错误。
复现代码
import pandas as pd import random import numpy as np import csv import os # 创建测试文件:两列,包含整数0-19 data=pd.DataFrame({'col1':list(range(10)),'col2':list(range(10,20))}) data.to_csv('test_file.csv',index=False) n_chunks=2 # 示例中将文件拆分为2个小文件 # 创建对应每个小文件的DictWriter对象列表 file_names=[f"test_batch_{batch_no}.csv" for batch_no in list(range(n_chunks))] chunks=[csv.DictWriter(open(file_name,'w'),["col1","col2"]) for file_name in file_names] # 为每个小文件写入表头 for chunk in chunks: chunk.writeheader() # 将原文件每行随机分配到小文件中 with open("test_file.csv",newline='') as data: reader=csv.DictReader(data) for line in reader: i=random.randint(0,n_chunks-1) chunks[i].writerow(line) # 读取小文件时触发错误 for file_name in file_names: chunk=pd.read_csv(file_name)
报错栈
Traceback (most recent call last): File "[...]/main.py", line 29, in <module> chunk=pd.read_csv(file_name) ^^^^^^^^^^^^^^^^^^^^^^ File "[...]/.venv/lib/python3.12/site-packages/pandas/io/parsers/readers.py", line 1026, in read_csv return _read(filepath_or_buffer, kwds) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "[...]/.venv/lib/python3.12/site-packages/pandas/io/parsers/readers.py", line 620, in _read parser = TextFileReader(filepath_or_buffer, **kwds) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "[...]/.venv/lib/python3.12/site-packages/pandas/io/parsers/readers.py", line 1620, in __init__ self._engine = self._make_engine(f, self.engine) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "[...]/.venv/lib/python3.12/site-packages/pandas/io/parsers/readers.py", line 1898, in _make_engine return mapping[engine](f, **self.options) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "[...].venv/lib/python3.12/site-packages/pandas/io/parsers/c_parser_wrapper.py", line 93, in __init__ self._reader = parsers.TextReader(src, **kwds) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "parsers.pyx", line 581, in pandas._libs.parsers.TextReader.__cinit__ pandas.errors.EmptyDataError: No columns to parse from file
问题原因与解决方法
核心问题
你在创建csv.DictWriter时直接用open(file_name,'w')打开文件,但未显式关闭文件句柄。操作系统会将文件内容暂存到缓冲区,未关闭句柄时,缓冲区内容可能还没写入磁盘,导致pandas读取到的是空文件(或不完整文件)。
修复后的代码
import pandas as pd import random import csv # 创建测试文件 data = pd.DataFrame({'col1': list(range(10)), 'col2': list(range(10,20))}) data.to_csv('test_file.csv', index=False) n_chunks = 2 file_names = [f"test_batch_{batch_no}.csv" for batch_no in range(n_chunks)] # 单独保存文件句柄和DictWriter对象,避免隐式打开未关闭 chunk_writers = [] for file_name in file_names: # 添加newline=''符合csv模块官方推荐写法,避免换行符处理异常 f = open(file_name, 'w', newline='') writer = csv.DictWriter(f, ["col1", "col2"]) chunk_writers.append((f, writer)) # 写入表头 for f, writer in chunk_writers: writer.writeheader() # 随机分配行到小文件 with open("test_file.csv", newline='') as data_file: reader = csv.DictReader(data_file) for line in reader: i = random.randint(0, n_chunks-1) chunk_writers[i][1].writerow(line) # 关键步骤:手动关闭所有文件句柄,确保缓冲区内容写入磁盘 for f, writer in chunk_writers: f.close() # 现在可以正常读取小文件 for file_name in file_names: chunk = pd.read_csv(file_name) print(chunk)
补充说明
- 使用
newline=''是csv模块的推荐写法,能避免不同操作系统下的换行符处理问题 - 如果追求更安全的文件管理,也可以为每个小文件单独使用
with上下文管理器,但频繁打开/关闭会降低大文件处理的性能,保持句柄打开更高效
内容的提问来源于stack exchange,提问作者joris_94
相关产品推荐
相关产品推荐

