Я хочу знать, как получить размер объектов, таких как строка, целое число и т. Д. В Python.
Связанный вопрос: сколько байтов на элемент содержится в списке Python (кортеж)?
Я использую файл XML, который содержит поля размера, которые определяют размер значения. Я должен разобрать этот XML и сделать свое кодирование. Когда я хочу изменить значение определенного поля, я проверю поле размера этого значения. Здесь я хочу сравнить, имеет ли новое значение, которое я собираюсь ввести, такой же размер, как в XML. Мне нужно проверить размер нового значения. В случае строки я могу сказать ее длину. Но в случае int, float и т. Д. Я запутался.
__sizeof__
метод для вашего класса. Встроенныйdict
класс python определяет его, поэтому вы получаете правильный результат при использовании объекта типаdict
.getsizeof
функцию малозначимой из коробки.Ответ «Просто используйте sys.getsizeof» не является полным ответом.
Этот ответ делает работу для встроенных объектов напрямую, но он не учитывает , что эти объекты могут содержать, в частности, какие типы, такие как пользовательские объекты, кортежи, списки, dicts и наборы содержат. Они могут содержать экземпляры друг друга, а также числа, строки и другие объекты.
Более полный ответ
Используя 64-битный Python 3.6 из дистрибутива Anaconda, с помощью sys.getsizeof, я определил минимальный размер следующих объектов и обратите внимание, что устанавливает и диктует предварительное выделение пространства, поэтому пустые не увеличиваются снова до истечения заданного количества (что может зависит от реализации языка):
Python 3:
Как вы это интерпретируете? Хорошо, скажем, у вас есть набор из 10 предметов. Если каждый элемент имеет размер 100 байт, то насколько велика вся структура данных? Сам набор равен 736, потому что его размер увеличился до 736 байт. Затем вы добавляете размер элементов, так что всего получается 1736 байт.
Некоторые предостережения для определений функций и классов:
Обратите внимание, что каждое определение класса имеет структуру прокси
__dict__
(48 байт) для атрибутов класса. У каждого слота есть дескриптор (например, aproperty
) в определении класса.Временные интервалы начинаются с 48 байтов в первом элементе и увеличиваются на 8 каждый. Только пустые объекты со слотами имеют 16 байтов, и экземпляр без данных имеет очень мало смысла.
Кроме того, каждое определение функции имеет объекты кода, может быть строки документации и другие возможные атрибуты, даже a
__dict__
.Также обратите внимание, что мы используем это,
sys.getsizeof()
потому что мы заботимся об использовании предельного пространства, которое включает в себя накладные расходы на сборку мусора для объекта, из документов :Также обратите внимание, что изменение размеров списков (например, повторное добавление к ним) заставляет их предварительно распределять пространство, аналогично наборам и диктам. Из исходного кода listobj.c :
Исторические данные
Анализ Python 2.7, подтвержденный
guppy.hpy
иsys.getsizeof
:Обратите внимание, что словари ( но не наборы ) получили более компактное представление в Python 3.6
Я думаю, что 8 байтов на каждый элемент для ссылки имеют большой смысл на 64-битной машине. Эти 8 байтов указывают на место в памяти, в котором находится содержащийся элемент. 4 байта имеют фиксированную ширину для юникода в Python 2, если я правильно помню, но в Python 3 str становится юникодом ширины, равной максимальной ширине символов.
(И больше о слотах, смотрите этот ответ )
Более полная функция
Нам нужна функция, которая ищет элементы в списках, кортежах, множествах, dicts,
obj.__dict__
s иobj.__slots__
, А также в других вещах, о которых мы еще не думали.Мы хотим положиться на
gc.get_referents
этот поиск, потому что он работает на уровне C (что делает его очень быстрым). Недостатком является то, что get_referents может возвращать избыточные члены, поэтому мы должны убедиться, что мы не удваиваем счет.Классы, модули и функции являются синглетонами - они существуют один раз в памяти. Нас не очень интересует их размер, так как мы мало что можем с ними поделать - они являются частью программы. Поэтому мы не будем считать их, если на них будут ссылаться.
Мы собираемся использовать черный список типов, поэтому мы не включаем всю программу в наш счетчик размеров.
Чтобы сопоставить это со следующей функцией из белого списка, большинство объектов знают, как обходить себя для целей сборки мусора (это примерно то, что мы ищем, когда хотим узнать, насколько дороги в памяти определенные объекты. Эта функциональность используется
gc.get_referents
.) Однако эта мера будет гораздо более обширной, чем мы предполагали, если мы не будем осторожны.Например, функции знают достаточно много о модулях, в которых они созданы.
Другое отличие состоит в том, что строки, являющиеся ключами в словарях, обычно интернированы, поэтому они не дублируются. Проверка
id(key)
также позволит нам избежать подсчета дубликатов, что мы и сделаем в следующем разделе. Решение черного списка пропускает подсчет ключей, которые являются строками в целом.Типы в белых списках, Рекурсивный посетитель (старая реализация)
Чтобы охватить большинство этих типов самостоятельно, вместо того, чтобы полагаться на модуль gc, я написал эту рекурсивную функцию, чтобы попытаться оценить размер большинства объектов Python, включая большинство встроенных функций, типов в модуле коллекций и пользовательских типов (в слотах и в других случаях). ,
Функция такого типа дает гораздо более детальный контроль над типами, которые мы собираемся рассчитывать на использование памяти, но есть опасность пропустить типы:
И я проверил это довольно случайно (я должен протестировать это):
Эта реализация разбивает определения классов и определения функций, потому что мы не используем все их атрибуты, но поскольку они должны существовать в процессе только один раз в памяти, их размер на самом деле не имеет большого значения.
источник
В Pympler ПАКЕТ в
asizeof
модуль может сделать это.Используйте следующим образом:
В отличие от этого
sys.getsizeof
, он работает для ваших самодельных объектов . Это даже работает с NumPy.Как уже упоминалось ,
И если вам нужен другой взгляд на живые данные, Pympler's
источник
org.apache.spark.util.SizeEstimator
может быть уместнымpympler
имеет возможность принимать во внимание размер исполняемого кода функций и других вызываемых объектов и объектов кода.TypeError
исключение: «Объект« NoneType »не может быть вызван» всякий раз, когда мой пользовательский объект имеет некоторый подобъект в своем «дереве» со значениемNone
. Есть ли быстрый способ обойти это?Для NumPy массивов
getsizeof
не работает - для меня он всегда возвращает 40 по некоторым причинам:Тогда (в ipython):
К счастью, хотя:
источник
getsizeof()
дает только размер объекта (заголовок массива), а не данные внутри. То же самое для контейнеров Python, гдеsys.getsizeof([1,2,4]) == sys.getsizeof([1,123**456,4]) == 48
, в то время какsys.getsizeof(123**456) = 436
getsizeof()
функция была изменена в какой-то момент, чтобы вернуть ожидаемое значение.Python 3.8 (Q1 2019) изменит некоторые результаты
sys.getsizeof
, как было объявлено здесь Рэймондом Хеттингером:Это происходит после проблемы 33597 и работы Инады Наоки (
methane
) над Compact PyGC_Head и PR 7043Смотрите коммит d5c875b :
источник
Это может быть сложнее, чем кажется, в зависимости от того, как вы хотите считать вещи. Например, если у вас есть список целых, хотите ли вы размер списка, содержащего ссылки на эти целые? (т. е. только список, а не то, что в нем содержится), или вы хотите включить фактические данные, на которые указывает, в этом случае вам нужно иметь дело с дублирующимися ссылками, и как предотвратить двойной счет, когда два объекта содержат ссылки на тот же объект.
Возможно, вы захотите взглянуть на один из профилировщиков памяти python, например pysizer, чтобы увидеть, соответствуют ли они вашим потребностям.
источник
Сам много раз сталкиваясь с этой проблемой, я написал небольшую функцию (вдохновленную ответом @ aaron-hall) и тесты, которые выполняют то, что я ожидал от sys.getsizeof:
https://github.com/bosswissam/pysize
Если вы заинтересованы в предыстории, вот она
РЕДАКТИРОВАТЬ: Прикрепление кода ниже для удобства. Чтобы увидеть самый последний код, пожалуйста, проверьте ссылку на github.
источник
Вот быстрый скрипт, который я написал на основе предыдущих ответов на размеры списка всех переменных
источник
Вы можете сериализовать объект, чтобы получить меру, тесно связанную с размером объекта:
Если вы хотите измерить объекты, которые не могут быть засечены (например, из-за лямбда-выражений), Cloudpickle может быть решением.
источник
Используйте sys.getsizeof (), если вы НЕ хотите включать размеры связанных (вложенных) объектов.
Однако, если вы хотите подсчитать подобъекты, вложенные в списки, подсказки, наборы, кортежи - и, как правило, это то, что вы ищете - используйте рекурсивную функцию deep sizeof (), как показано ниже:
Вы также можете найти эту функцию в отличном наборе инструментов вместе со многими другими полезными однострочниками:
https://github.com/mwojnars/nifty/blob/master/util.py
источник
Если вам не нужен точный размер объекта, но нужно примерно знать, насколько он велик, один быстрый (и грязный) способ - запустить программу, не спать в течение длительного периода времени и проверить использование памяти (например, : Монитор активности Mac) этим конкретным процессом python. Это будет эффективно, когда вы пытаетесь найти размер одного большого объекта в процессе Python. Например, недавно я хотел проверить использование памяти новой структурой данных и сравнить ее с установленной структурой данных Python. Сначала я записал элементы (слова из большой общедоступной книги) в набор, затем проверил размер процесса, а затем проделал то же самое с другой структурой данных. Я обнаружил, что процесс Python с множеством занимает вдвое больше памяти, чем новая структура данных. Опять же, вы бы не Я не могу точно сказать, что память, используемая процессом, равна размеру объекта. По мере того как размер объекта становится большим, он становится близким, поскольку объем памяти, используемой остальной частью процесса, становится незначительным по сравнению с размером объекта, который вы пытаетесь отслеживать.
источник
Вы можете использовать getSizeof (), как указано ниже, чтобы определить размер объекта
источник
Я использую этот трюк ... Возможно, он не будет точным на небольших объектах, но я думаю, что он гораздо точнее для сложного объекта (например, поверхность пигмея), а не sys.getsizeof ()
На моем Windows 10, Python 3.7.3, вывод:
источник