Python MemoryError:无法分配数组内存

ste*_*esu 12 python memory csv file-io numpy

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

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

我从那以后尝试了其他几种策略,包括:

  1. import fileinput 并一次读取一行,将它们附加到数组中
  2. np.fromstring 读完整个文件后
  3. np.genfromtext
  4. 手动解析文件(因为所有数据都是整数,这很容易编码)

每种方法都给了我相同的结果.MemoryError大约512 MB.想知道是否有一些特殊的512MB,我创建了一个简单的测试程序,它填满了内存,直到python崩溃:

str = " " * 511000000 # Start at 511 MB
while 1:
    str = str + " " * 1000 # Add 1 KB at a time
Run Code Online (Sandbox Code Playgroud)

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

在我发现这篇文章之前,我无聊地google'd:Python大文件上的内存不足(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
Run Code Online (Sandbox Code Playgroud)

iter_loadtxt("data/training_nohead.csv")这次调用给出了稍微不同的错误:

MemoryError: cannot allocate array memory
Run Code Online (Sandbox Code Playgroud)

谷歌搜索这个错误我只找到一个,不是那么有用,发布:内存错误(MemoryError)创建一个布尔NumPy数组(Python)

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

ste*_*esu 5

在@JF Sebastian 的帮助下,我得出了以下答案:

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

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

num_rows = 0
for line in open("data/training_nohead.csv")
    num_rows += 1
Run Code Online (Sandbox Code Playgroud)

对于列数,如果每行都有相同的列数,那么您可以只计算第一行,否则您需要跟踪最大值。

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)
Run Code Online (Sandbox Code Playgroud)

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

  • 注意:您可以在此处使用“for i, line in enumerate(file)”和“ncols = max(ncols, len(line.split(',')))”内置函数。一般来说(不是在这种情况下),cvs 行可能跨越多个物理行,即枚举 csv 行的正确方法是:`for i, row in enumerate(csv.reader(file))`。 (2认同)