You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

大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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 07:08:16