Python MemoryError:无法分配数组内存

时间:2013-12-06 13:29:11

标签: python memory csv file-io numpy

我有一个250 MB的CSV文件,我需要读取~7,000行和~9000列。每行代表一个图像,每列是一个像素(灰度值0-255)

我从一个简单的np.loadtxt("data/training_nohead.csv",delimiter=",")开始,但这给了我一个内存错误。我认为这很奇怪,因为我正在运行64位Python,安装了8个内存,并且在使用大约512 MB之后就死了。

我已经尝试了其他几种策略,包括:

  1. import fileinput并一次读取一行,将它们附加到数组
  2. 阅读整个文件后
  3. np.fromstring
  4. np.genfromtext
  5. 手动解析文件(因为所有数据都是整数,这很容易编码)
  6. 每种方法都给了我相同的结果。 MemoryError大约512 MB。想知道是否有一些特殊的512MB,我创建了一个简单的测试程序,它填满了内存,直到python崩溃:

    str = " " * 511000000 # Start at 511 MB
    while 1:
        str = str + " " * 1000 # Add 1 KB at a time
    

    这样做直到大约1演出才崩溃。我也是,为了好玩,尝试了:str = " " * 2048000000(填写2场演出) - 这顺便说一句。填写RAM,从不抱怨。所以问题不在于我可以分配的RAM总量,而是似乎是我可以分配内存的TIMES数量......

    我无趣地谷歌,直到找到这篇文章:Python out of memory on large CSV file (numpy)

    我完全复制了答案中的代码:

    def iter_loadtxt(filename, delimiter=',', skiprows=0, dtype=float):
        def iter_func():
            with open(filename, 'r') as infile:
                for _ in range(skiprows):
                    next(infile)
                for line in infile:
                    line = line.rstrip().split(delimiter)
                    for item in line:
                        yield dtype(item)
            iter_loadtxt.rowlength = len(line)
    
        data = np.fromiter(iter_func(), dtype=dtype)
        data = data.reshape((-1, iter_loadtxt.rowlength))
        return data
    

    此次调用iter_loadtxt("data/training_nohead.csv")会出现略有不同的错误:

    MemoryError: cannot allocate array memory
    

    谷歌搜索此错误我只发现一个,不太有用,发布:Memory error (MemoryError) when creating a boolean NumPy array (Python)

    当我运行Python 2.7时,这不是我的问题。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:4)

在@ J.F的帮助下。塞巴斯蒂安我提出了以下答案:

train = np.empty([7049,9246])
row = 0
for line in open("data/training_nohead.csv")
    train[row] = np.fromstring(line, sep=",")
    row += 1

当然,这个答案假定了行数和列数的先验知识。如果您事先没有此信息,则行数总是需要一段时间来计算,因为您必须读取整个文件并计算\n个字符。这样的东西就足够了:

num_rows = 0
for line in open("data/training_nohead.csv")
    num_rows += 1

对于每列具有相同列数的列数,您只需计算第一行,否则需要跟踪最大值。

num_rows = 0
max_cols = 0
for line in open("data/training_nohead.csv")
    num_rows += 1
    tmp = line.split(",")
    if len(tmp) > max_cols:
        max_cols = len(tmp)

此解决方案最适合数值数据,因为包含逗号的字符串可能会使事情变得复杂。

答案 1 :(得分:0)

这是一个古老的讨论,但可能对现在的人有所帮助。

我想我知道为什么 str = str + " " * 1000str = " " * 2048000000 失败的原因

运行第一个时,我相信操作系统需要在内存中分配新对象 str + " " * 1000,然后才引用名称 str。在将名称“str”引用到新对象之前,它无法摆脱第一个。 这意味着操作系统需要在同一时间两次分配大约 'str' 对象,使其能够只为 1 gig 而不是 2 gig 进行分配。 我相信使用下一个代码将从您的操作系统中获得与单一分配相同的最大内存:

str = " " * 511000000
while(1):
    l = len(str)
    str = " "
    str = " " * (len + 1000)

如果我错了,请随时告诉我