Python-读取巨大的.csv文件

发布于 2021-02-02 23:13:24

我目前正在尝试从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(不确定您需要什么信息)。

关注者
0
被浏览
92
1 个回答
  • 面试哥
    面试哥 2021-02-02
    为面试而生,有面试问题,就找面试哥。

    你正在将所有行读入列表,然后处理该列表。不要那样做。

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

    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
    

    现在,你仅在内存中保留一行,而不是每个条件存储数千行。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看