python - 读取一个巨大的 .csv 文件

标签 python python-2.7 file csv

我目前正在尝试从 Python 2.7 中的 .csv 文件中读取数据,该文件最多有 100 万行和 200 列(文件范围从 100mb 到 1.6gb)。我可以对 300,000 行以下的文件执行此操作(非常缓慢),但是一旦超过此值,我就会出现内存错误。我的代码如下所示:

def getdata(filename, criteria):
    data=[]
    for criterion in criteria:
        data.append(getstuff(filename, criteron))
    return data

def getstuff(filename, criterion):
    import csv
    data=[]
    with open(filename, "rb") as csvfile:
        datareader=csv.reader(csvfile)
        for row in datareader: 
            if row[3]=="column header":
                data.append(row)
            elif len(data)<2 and row[3]!=criterion:
                pass
            elif row[3]==criterion:
                data.append(row)
            else:
                return data

getstuff 函数中的 else 子句的原因是所有符合条件的元素都会一起列在 csv 文件中,所以当我通过它们时我会离开循环以节省时间。

我的问题是:

  1. 我怎样才能让它与更大的文件一起使用?

  2. 有什么方法可以让它更快?

我的电脑有 8GB RAM,运行 64 位 Windows 7,处理器为 3.40 GHz(不确定您需要什么信息)。

最佳答案

您正在将所有行读入一个列表,然后处理该列表。 不要这样做

在生成行时对其进行处理。如果您需要先过滤数据,请使用生成器函数:

import csv

def getstuff(filename, criterion):
    with open(filename, "rb") as csvfile:
        datareader = csv.reader(csvfile)
        yield next(datareader)  # yield the header row
        count = 0
        for row in datareader:
            if row[3] == criterion:
                yield row
                count += 1
            elif count:
                # done when having read a consecutive series of rows 
                return

我还简化了您的过滤器测试;逻辑相同,但更简洁。

因为您只匹配符合条件的单个行序列,您也可以使用:

import csv
from itertools import dropwhile, takewhile

def getstuff(filename, criterion):
    with open(filename, "rb") as csvfile:
        datareader = csv.reader(csvfile)
        yield next(datareader)  # yield the header row
        # first row, plus any subsequent rows that match, then stop
        # reading altogether
        # Python 2: use `for row in takewhile(...): yield row` instead
        # instead of `yield from takewhile(...)`.
        yield from takewhile(
            lambda r: r[3] == criterion,
            dropwhile(lambda r: r[3] != criterion, datareader))
        return

您现在可以直接循环 getstuff()。在 getdata() 中执行相同操作:

def getdata(filename, criteria):
    for criterion in criteria:
        for row in getstuff(filename, criterion):
            yield row

现在在您的代码中直接循环 getdata():

for row in getdata(somefilename, sequence_of_criteria):
    # process row

您现在只在内存中保存 一行,而不是每个标准都有数千行。

yield 使函数成为 generator function ,这意味着在你开始循环之前它不会做任何工作。

关于python - 读取一个巨大的 .csv 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17444679/

相关文章:

python - 需要 Django-easy-pdf : xhtml2pdf reporting reportlab 2. 2+,但已安装 3.0

Python:回调问题

python-2.7 - Python调整图像大小并发送到谷歌视觉功能

python - 相当于 Python 中的 "genvarname"

c#类库使用文件

python - 在Python(可能是pandas)中从文件读取数组时,处理和跳过第一行(包含元数据)的优雅方法?

python - Numpy:通过重复序列添加垫来创建上三角矩阵

Python2.7 打印 unicode 字符串仍然出现 UnicodeEncodeError : 'ascii' codec can't encode character . .. 序号不在范围内(128)

java - 从包中访问文件

c - 指针关闭后,无法使用system()命令删除该文件,并显示该文件已被其他程序使用