Преобразование списка int в список строк занимает слишком много памяти в Python

#python #python-3.x #string #list

Вопрос:

Мне нужно хранить целые числа в виде строки. Например. — [1,2,3] будет сохранено как ‘1;2;3’. Для этого мне нужно сначала преобразовать список целых чисел в список строк. Но использование памяти для этого преобразования огромно.

Пример кода, показывающий проблему.

 from sys import getsizeof import tracemalloc  tracemalloc.start()  curr, peak = tracemalloc.get_traced_memory() print((f'Current: {round(curr/1e6)} MBnPeak: {round(peak/1e6)} MB'))  print()  list_int = [1]*int(1e6)  curr, peak = tracemalloc.get_traced_memory() print((f'Current: {round(curr/1e6)} MBnPeak: {round(peak/1e6)} MB')) print(f'Size of list_int: {getsizeof(list_int)/1e6} MB')  print()  list_str = [str(i) for i in list_int]  curr, peak = tracemalloc.get_traced_memory() print((f'Current: {round(curr/1e6)} MBnPeak: {round(peak/1e6)} MB')) print(f'Size of list_str: {getsizeof(list_str)/1e6} MB')  

Выход:

 Current: 0 MB Peak: 0 MB  Current: 8 MB Peak: 8 MB Size of list_int: 8.000056 MB  Current: 66 MB Peak: 66 MB Size of list_str: 8.448728 MB  

Память, занимаемая обоими списками, одинакова (8 МБ), но память, используемая программой во время преобразования, огромна (66 МБ).

Как я могу решить эту проблему с памятью?

Редактировать: Мне нужно преобразовать его в строку, поэтому ';'.join(list_str) в конце я запущу. Итак, даже если я использую, скажем , генератор/итерацию list_str = map(str, list_int) , использование памяти будет одинаковым.

Комментарии:

1. Я не знаю, почему это происходит, но как насчет использования итеративного? Например, list_str = map(str, list_int) . Это не будет хранить весь список строк, так что вы будете использовать меньше памяти заранее.

2. @j1-ли Да, но, как я уже упоминал, моя конечная цель-создать строку, чтобы с помощью итерации, как вы упомянули, когда я запускаю ‘;’.join(list_str), использование памяти становится одинаковым.

3. Ах, вы правы.

4. @aniketsharma00411 с использованием памяти генератора будет слишком меньше по сравнению с пониманием списка . Смотрите мой ответ ниже.

5. @TimRoberts 66 МБ не велик, но когда я запускаю что-то подобное в своем приложении, потребление памяти для list_str размером 60 МБ составляет 560 МБ, что приводит к сбою моего сервера. Код, который я показал, является лишь примером.

Ответ №1:

Вместо этого используйте Numpy. Попробуй это

 from sys import getsizeof import tracemalloc import numpy as np  tracemalloc.start()  arr = np.ones((1000000,), dtype=np.str) for i in [1]*int(1e6):  arr[i] = str(i)  curr, peak = tracemalloc.get_traced_memory() print((f'Current: {round(curr/1e6)} MBnPeak: {round(peak/1e6)} MB')) print(f'Size of list_str: {getsizeof(list(arr))/1e6} MB')  

Вывод с улучшением бита, я думаю

 Current: 4 MB Peak: 12 MB Size of list_str: 9.000112 MB  

Комментарии:

1. @j1-ли да, вы правы. Сейчас я это исправлю.

2. @j1-ли использовал dtype=np.str теперь элементы массива являются строками

3. В этом случае также,»;». join(arr) увеличивает использование памяти.