Python MemoryError: не удается выделить память массива

у меня есть файл CSV 250 MB, который мне нужно прочитать с ~7000 строк и ~9000 столбцов. Каждая строка представляет изображение, а каждый столбец-пиксель (значение в оттенках серого 0-255)

я начал с простого np.loadtxt("data/training_nohead.csv",delimiter=",") но это дало мне ошибку памяти. Я подумал, что это странно, так как я запускаю 64-битный Python с 8 гигабайтами памяти, и он умер после использования только около 512 МБ.

С тех пор я пробовал несколько других тактик, в том числе:

  1. import fileinput и читайте по одной строке за раз, добавляя их в массив
  2. np.fromstring после прочтения во всем файле
  3. np.genfromtext
  4. ручной разбор файла (так как все данные целые, это было довольно легко кодировать)

каждый метод дал мне тот же результат. MemoryError около 512 МБ. Задаваясь вопросом, есть ли что-то особенное в 512MB, я создал простую тестовую программу, которая заполнила память до python разбился:

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

это не произошло до 1 концерта. Я также, просто для удовольствия, попробовал:str = " " * 2048000000 (заполните 2 концерта) - это прошло без сучка и задоринки. Заполнил ОЗУ и никогда не жаловался. Таким образом, проблема заключается не в общем объеме ОЗУ, который я могу выделить, а в том, сколько раз я могу выделить память...

Я google вокруг бесплодно, пока не нашел этот пост:Python из памяти в большом CSV-файле (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

Googling эта ошибка я нашел только один, не очень полезный, сообщение:Ошибка памяти (MemoryError) при создании логического массива NumPy (Python)

поскольку я запускаю Python 2.7, это не было моей проблемой. Любая помощь будет оценена.

1 ответов


С некоторой помощью @J. F. Sebastian я разработал следующий ответ:

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)

это решение лучше всего работает для числовых данных, так как строка, содержащая запятую, может действительно усложнить ситуацию.