23

在一个基本的我有下一个过程。

import csv
reader = csv.reader(open('huge_file.csv', 'rb'))

for line in reader:
    process_line(line)

请参阅此相关问题。我想每 100 行发送一次流程线,以实现批量分片。

实现相关答案的问题是 csv 对象不可订阅且不能使用 len。

>>> import csv
>>> reader = csv.reader(open('dataimport/tests/financial_sample.csv', 'rb'))
>>> len(reader)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object of type '_csv.reader' has no len()
>>> reader[10:]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '_csv.reader' object is unsubscriptable
>>> reader[10]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '_csv.reader' object is unsubscriptable

我该如何解决这个问题?

4

3 回答 3

28

只需reader将其包装成list. 显然这会破坏非常大的文件(请参阅下面的更新中的替代方案):

>>> reader = csv.reader(open('big.csv', 'rb'))
>>> lines = list(reader)
>>> print lines[:100]
...

进一步阅读:如何在 Python 中将列表拆分为大小均匀的块?


更新 1(列表版本):另一种可能的方法是处理每个卡盘,因为它在遍历行时到达:

#!/usr/bin/env python

import csv
reader = csv.reader(open('4956984.csv', 'rb'))

chunk, chunksize = [], 100

def process_chunk(chuck):
    print len(chuck)
    # do something useful ...

for i, line in enumerate(reader):
    if (i % chunksize == 0 and i > 0):
        process_chunk(chunk)
        del chunk[:]  # or: chunk = []
    chunk.append(line)

# process the remainder
process_chunk(chunk)

更新 2(生成器版本):我没有对其进行基准测试,但也许您可以通过使用块生成器来提高性能:

#!/usr/bin/env python

import csv
reader = csv.reader(open('4956984.csv', 'rb'))

def gen_chunks(reader, chunksize=100):
    """ 
    Chunk generator. Take a CSV `reader` and yield
    `chunksize` sized slices. 
    """
    chunk = []
    for i, line in enumerate(reader):
        if (i % chunksize == 0 and i > 0):
            yield chunk
            del chunk[:]  # or: chunk = []
        chunk.append(line)
    yield chunk

for chunk in gen_chunks(reader):
    print chunk # process chunk

# test gen_chunk on some dummy sequence:
for chunk in gen_chunks(range(10), chunksize=3):
    print chunk # process chunk

# => yields
# [0, 1, 2]
# [3, 4, 5]
# [6, 7, 8]
# [9]

正如@totalhack 指出的那样,有一个小问题:

请注意,这会一遍又一遍地产生具有不同内容的相同对象。如果您计划在每次迭代之间使用块做所有需要的事情,这很好用。

于 2011-02-10T12:26:11.487 回答
3

我们可以使用 pandas 模块来处理这些大的 csv 文件。

df = pd.DataFrame()
temp = pd.read_csv('BIG_File.csv', iterator=True, chunksize=1000)
df = pd.concat(temp, ignore_index=True)
于 2018-12-14T09:21:23.510 回答
2

没有一个方法可以对所有.csv文件执行此操作。您应该能够使用file.seek跳过文件的一部分将文件分成块。然后你必须一次扫描一个字节才能找到行尾。您可以独立处理这两个块。类似以下(未经测试)的代码应该可以帮助您入门。

file_one = open('foo.csv')
file_two = open('foo.csv') 
file_two.seek(0, 2)     # seek to the end of the file
sz = file_two.tell()    # fetch the offset
file_two.seek(sz / 2)   # seek back to the middle
chr = ''
while chr != '\n':
    chr = file_two.read(1)
# file_two is now positioned at the start of a record
segment_one = csv.reader(file_one)
segment_two = csv.reader(file_two)

我不知道你怎么知道你已经完成了遍历segment_one。如果 CSV 中有一个列是行 ID,那么segment_one当您遇到segment_two.

于 2011-02-10T12:37:38.047 回答