#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) увеличивает использование памяти.