Python "случайный" MemoryError - PullRequest
       16

Python "случайный" MemoryError

3 голосов
/ 27 июня 2019

Я хотел бы понять, что происходит с MemoryError, которая кажется более или менее случайной. Я запускаю программу на Python 3 в Docker и на виртуальной машине Azure (2CPU и 7 ГБ ОЗУ).

Для простоты программа работает с двоичными файлами, которые читаются определенной библиотекой (там нет проблем), затем я объединяю их по пиру файлов и, наконец, вставляю данные в базу данных.
Набор данных, который я получаю после слияния (и перед вставкой в ​​БД), представляет собой фрейм данных Pandas, который содержит около ~ 2,8M строк и 36 столбцов .

Для вставки в базу данных я использую REST API, который обязывает меня вставлять файл порциями. Перед этим я преобразую датафрам в буфер StringIO с помощью этой функции:

# static method from Utils class
@staticmethod
def df_to_buffer(my_df):
    count_row, count_col = my_df.shape
    buffer = io.StringIO()  #creating an empty buffer
    my_df.to_csv(buffer, index=False)  #filling that buffer
    LOGGER.info('Current data contains %d rows and %d columns, for a total 
    buffer size of %d bytes.', count_row, count_col, buffer.tell())
    buffer.seek(0) #set to the start of the stream
    return buffer

Так что в моей "основной" программе поведение таково:

# transform the dataframe to a StringIO buffer
file_data = Utils.df_to_buffer(file_df)
buffer_chunk_size = 32000000 #32MB
while True:
    data = file_data.read(buffer_chunk_size)
    if data:
        ...
        # do the insert stuff
        ...
    else:
        # whole file has been loaded
        break
# loop is over, close the buffer before processing a new file
file_data.close()

Проблема:
Иногда я могу вставить 2 или 3 файла подряд. Иногда возникает ошибка MemoryError в случайный момент (но всегда, когда он собирается вставить новый файл).
Ошибка возникает на первой итерации вставки файла (никогда не в середине файла). В частности, происходит сбой в строке, выполняющей чтение по блоку file_data.read(buffer_chunk_size)

Я слежу за памятью во время процесса (используя htop): она никогда не превышает 5,5 ГБ памяти и, особенно, когда происходит сбой, в этот момент она использует ~ 3,5 ГБ используемой памяти. ..

Любая информация или советы будут оценены, Благодарю. :)

EDIT
Я смог отладить и идентифицировать проблему, но еще не решил ее.
Это происходит, когда я читаю буфер StringIO по чанку. Блок данных значительно увеличивает потребление оперативной памяти, так как это большой str, который содержит 320000000 символов файла. Я попытался уменьшить его с 32000000 до 16000000. Мне удалось вставить некоторые файлы, но через некоторое время снова возникает ошибка MemoryError ... Я пытаюсь уменьшить ее до 8000000 прямо сейчас.

...