Я хочу знать, как получить размер таких объектов, как строка, целое число и т. д. В Python.
Связанный вопрос: Сколько байтов на элемент в списке (кортеже) Python?
Я использую XML-файл, который содержит поля размера, в которых указывается размер значения. Я должен проанализировать этот XML и написать код. Когда я хочу изменить значение определенного поля, я проверю поле размера этого значения. Здесь я хочу сравнить, имеет ли новое значение, которое я собираюсь ввести, тот же размер, что и в XML. Мне нужно проверить размер нового значения. В случае строки я могу сказать ее длину. Но в случае int, float и т. д. Я запутался.






Просто используйте функцию sys.getsizeof, определенную в модуле sys.
sys.getsizeof(object[, default]):Return the size of an object in bytes. The object can be any type of object. All built-in objects will return correct results, but this does not have to hold true for third-party extensions as it is implementation specific.
Only the memory consumption directly attributed to the object is accounted for, not the memory consumption of objects it refers to.
The
defaultargument allows to define a value which will be returned if the object type does not provide means to retrieve the size and would cause aTypeError.
getsizeofcalls the object’s__sizeof__method and adds an additional garbage collector overhead if the object is managed by the garbage collector.See recursive sizeof recipe for an example of using
getsizeof()recursively to find the size of containers and all their contents.
Пример использования в Python 3.0:
>>> import sys
>>> x = 2
>>> sys.getsizeof(x)
24
>>> sys.getsizeof(sys.getsizeof)
32
>>> sys.getsizeof('this')
38
>>> sys.getsizeof('this also')
48
Если вы используете python <2.6 и у вас нет sys.getsizeof, вы можете вместо этого использовать этот обширный модуль. Но никогда не использовал.
Умм ... sys.sizeof (c) равно 32, даже если у экземпляра класса 50 атрибутов! Кажется, что-то не так! Попробуйте это: d = {k: v for k, v in zip('ABCDEFGHIJKLMNOPQRSTUVWXYabcdefghijklmnopqrstuvwxy', range(50))}class C(object): def __init__(self, **kwargs): _ = {setattr(self, k, v) for k, v in kwargs.items()}c = C(**d)sys.getsizeof(d) 1676 sys.getsizeof(c) 32
@ChaimG, потому что каждый объект использует только 32 байта !! Остальное - это ссылки на другие объекты. Если вы хотите учитывать объекты, на которые имеются ссылки, вам необходимо определить метод __sizeof__ для своего класса. Встроенный класс python dict определяет его, поэтому вы получаете правильный результат при использовании объекта типа dict.
Заявление об отказе от ответственности и исключения из этого рабочего документа охватывают почти все варианты использования, делающие функцию getsizeof малоценной из коробки.
Очевидно, sys.getsizeof недоступен в PyPy. Есть ли общий обходной путь для этого?
почему целое число 2 хранится в 24 байтах?
@SaherAhwal это не просто целое число, а полноценный объект с методами, атрибутами, адресами ...
Это может быть сложнее, чем кажется, в зависимости от того, как вы хотите считать. Например, если у вас есть список целых чисел, хотите ли вы, чтобы размер списка, содержащего Рекомендации, соответствовал целым числам? (т.е. только список, а не то, что в нем содержится), или вы хотите включить фактические данные, на которые указывают, и в этом случае вам нужно иметь дело с повторяющимися ссылками и как предотвратить двойной подсчет, когда два объекта содержат ссылки на тот же объект.
Вы можете взглянуть на один из профилировщиков памяти Python, например писатель, чтобы узнать, соответствуют ли они вашим потребностям.
Для массивов numpy getsizeof не работает - для меня он по какой-то причине всегда возвращает 40:
from pylab import *
from sys import getsizeof
A = rand(10)
B = rand(10000)
Затем (в ipython):
In [64]: getsizeof(A)
Out[64]: 40
In [65]: getsizeof(B)
Out[65]: 40
К счастью:
In [66]: A.nbytes
Out[66]: 80
In [67]: B.nbytes
Out[67]: 80000
> Все встроенные объекты будут возвращать правильные результаты, но это не обязательно должно выполняться для сторонних расширений, поскольку это зависит от реализации. docs.python.org/library/sys.html#sys.getsizeof
«Если вы используете массив numpy (docs.scipy.org/doc/numpy/reference/arrays.ndarray.html), вы можете использовать атрибут 'ndarray.nbytes', чтобы оценить его размер в памяти». stackoverflow.com/a/15591157/556413
Я бы предположил, что 40 байт - это правильно, однако getsizeof() дает вам только размер объекта (заголовок массива), а не данных внутри. То же самое для контейнеров python, где sys.getsizeof([1,2,4]) == sys.getsizeof([1,123**456,4]) == 48, а sys.getsizeof(123**456) = 436
Похоже, что функция getsizeof() была изменена в какой-то момент, чтобы вернуть ожидаемое значение.
Вот быстрый сценарий, который я написал на основе предыдущих ответов о размерах списка всех переменных.
for i in dir():
print (i, sys.getsizeof(eval(i)) )
Это не неправильно, это неоднозначно. sys.getsizeof всегда будет возвращать значение, поэтому нет необходимости терять производительность с помощью try..except.
о, это хороший момент, и я не думал об этом - код в той форме, в которой он сейчас, просто показывает, как он был написан в хронологическом порядке - сначала я знал о numpy (следовательно, nbytes), затем я нашел более общее решение . Спасибо вам за разъяснение _/\_
Модуль asizeof пакета Пимплер может это сделать.
Используйте следующим образом:
from pympler import asizeof
asizeof.asizeof(my_object)
В отличие от sys.getsizeof, это работает для ваших созданных вами объектов. Он даже работает с numpy.
>>> asizeof.asizeof(tuple('bcd'))
200
>>> asizeof.asizeof({'foo': 'bar', 'baz': 'bar'})
400
>>> asizeof.asizeof({})
280
>>> asizeof.asizeof({'foo':'bar'})
360
>>> asizeof.asizeof('foo')
40
>>> asizeof.asizeof(Bar())
352
>>> asizeof.asizeof(Bar().__dict__)
280
>>> A = rand(10)
>>> B = rand(10000)
>>> asizeof.asizeof(A)
176
>>> asizeof.asizeof(B)
80096
Как упомянул,
А если вам нужен другой взгляд на живые данные, Pympler's
module
muppyis used for on-line monitoring of a Python application and moduleClass Trackerprovides off-line analysis of the lifetime of selected Python objects.
эта функция довольно медленная для больших объектов. Существует ли «быстрый» эквивалент, который работает для самосозданных объектов?
Я еще не тестировал, но org.apache.spark.util.SizeEstimator может быть актуален
@Shuklaswag: если вы используете искру, вполне может быть. Как вы думаете, конверсия + оценка Java быстрее, чем встроенные методы Python? Или я неправильно понял?
Стоит отметить, что pympler имеет возможность учитывать размер исполняемого кода функций и других вызываемых объектов и объектов кода.
Я получаю исключение TypeError: «Объект« NoneType »не вызывается» всякий раз, когда мой настраиваемый объект имеет в своем «дереве» подобъект со значением None. Есть ли какое-нибудь быстрое решение?
@JamesHirschorn: Ты мог бы опубликовать отчет об ошибке. Не могли бы вы дать MCVE? Использование asizeof.asizeof({"hello": None}) и asizeof.asizeof({"hello": {"world": None}}) оба работали с Pympler 0.6.
Да, оба ваших примера у меня тоже сработали. Сложность с MCVE заключается в том, что мой код основан на клоне github другого автора. Будет ли достаточно не минимального CVE от github?
@JamesHirschorn: все, что нужно отлаживать, желательно с трассировкой стека, или попробовать json.dump рассматриваемого объекта.
@ serv-inc: Хорошо, я добавлю трассировку и json.dump в отчет об ошибке.
@JamesHirschorn: неплохо выглядит. Если json.dump не работает, возможно, pickle.dumps работает.
@ serv-inc: Сообщите мне, если я вам понадоблюсь, чтобы протестировать его, потому что в противном случае в моей программе не будет утечки памяти, поэтому во мне нет срочной необходимости.
Результаты в байтах, килобайтах, мегабайтах ...?
@ihavenoidea: bytes (просто представьте, что каждый объект python занимает 280 кбайт)
Столкнувшись с этой проблемой много раз, я написал небольшую функцию (вдохновленную ответом @aaron-hall) и тесты, которые делают то, что я ожидал от sys.getsizeof:
https://github.com/bosswissam/pysize
Если вас интересует предыстория, вот
Обновлено: прикрепите приведенный ниже код для удобства. Чтобы увидеть самый последний код, проверьте ссылку на github.
import sys
def get_size(obj, seen=None):
"""Recursively finds size of objects"""
size = sys.getsizeof(obj)
if seen is None:
seen = set()
obj_id = id(obj)
if obj_id in seen:
return 0
# Important mark as seen *before* entering recursion to gracefully handle
# self-referential objects
seen.add(obj_id)
if isinstance(obj, dict):
size += sum([get_size(v, seen) for v in obj.values()])
size += sum([get_size(k, seen) for k in obj.keys()])
elif hasattr(obj, '__dict__'):
size += get_size(obj.__dict__, seen)
elif hasattr(obj, '__iter__') and not isinstance(obj, (str, bytes, bytearray)):
size += sum([get_size(i, seen) for i in obj])
return size
Python 3.8 (первый квартал 2019 г.) изменит некоторые результаты sys.getsizeof, как объявлено здесь Раймонда Хеттингера:
Python containers are 8 bytes smaller on 64-bit builds.
tuple () 48 -> 40
list [] 64 ->56
set() 224 -> 216
dict {} 240 -> 232
Это происходит после того, как Выпуск 33597 и Инада Наоки (methane) поработали над Compact PyGC_Head и PR 7043
This idea reduces PyGC_Head size to two words.
Currently, PyGC_Head takes three words;
gc_prev,gc_next, andgc_refcnt.
gc_refcntis used when collecting, for trial deletion.gc_previs used for tracking and untracking.So if we can avoid tracking/untracking while trial deletion,
gc_prevandgc_refcntcan share same memory space.
См. совершить d5c875b:
Removed one
Py_ssize_tmember fromPyGC_Head.
All GC tracked objects (e.g. tuple, list, dict) size is reduced 4 or 8 bytes.
Если вам не нужен точный размер объекта, но нужно примерно знать, насколько он велик, один быстрый (и грязный) способ - позволить программе работать, спать в течение длительного периода времени и проверить использование памяти (например, : Монитор активности Mac) этим конкретным процессом Python. Это было бы эффективно, когда вы пытаетесь найти размер одного большого объекта в процессе Python. Например, недавно я хотел проверить использование памяти новой структурой данных и сравнить ее со структурой данных набора Python. Сначала я записал элементы (слова из большой общедоступной книги) в набор, затем проверил размер процесса, а затем проделал то же самое с другой структурой данных. Я обнаружил, что процесс Python с набором занимает в два раза больше памяти, чем новая структура данных. Опять же, вы не сможете точно сказать, что память, используемая процессом, равна размеру объекта. По мере увеличения размера объекта он становится близким, поскольку память, потребляемая остальной частью процесса, становится незначительной по сравнению с размером объекта, который вы пытаетесь отслеживать.
Вопрос спрашивает, как это сделать в питоне, а не просто найти использование памяти объектами Python из, а также использование монитора активности Mac или любого другого аналогичного программного обеспечения, не использующего программно python. При этом проверка использования памяти процессами python таким образом обычно является хорошим способом убедиться, что ничего не пошло не так ...
@TomWyllie, Спасибо, но голосование против этого ответа имеет негативный оттенок, что сам ответ неверен и ничего не дает. Упомянутый мной метод может не быть реализован в Python, но это удобный способ получить приблизительную оценку размера объекта Python. Я знал, что не отвечаю на точный вопрос, однако этот метод может быть полезен для кого-то другого, чтобы получить аналогичный результат.
Вы можете использовать getSizeof (), как указано ниже, для определения размера объекта.
import sys
str1 = "one"
int_element=5
print("Memory size of '"+str1+"' = "+str(sys.getsizeof(str1))+ " bytes")
print("Memory size of '"+ str(int_element)+"' = "+str(sys.getsizeof(int_element))+ " bytes")
Используйте sys.getsizeof (), если вы НЕ хотите включать размеры связанных (вложенных) объектов.
Однако, если вы хотите подсчитать подобъекты, вложенные в списки, словари, наборы, кортежи - а обычно это именно то, что вы ищете - используйте рекурсивную функцию глубокий sizeof (), как показано ниже:
import sys
def sizeof(obj):
size = sys.getsizeof(obj)
if isinstance(obj, dict): return size + sum(map(sizeof, obj.keys())) + sum(map(sizeof, obj.values()))
if isinstance(obj, (list, tuple, set, frozenset)): return size + sum(map(sizeof, obj))
return size
Вы также можете найти эту функцию в наборе инструментов изящный вместе со многими другими полезными однострочниками:
https://github.com/mwojnars/nifty/blob/master/util.py
Вы можете сериализовать объект, чтобы получить меру, которая тесно связана с размером объекта:
import pickle
## let o be the object whose size you want to measure
size_estimate = len(pickle.dumps(o))
Если вы хотите измерить объекты, которые нельзя мариновать (например, из-за лямбда-выражений), решением могут быть укроп или тучи.
Я использую этот трюк ... Может быть, не будет точным для небольших объектов, но я думаю, что он намного точнее для сложного объекта (например, поверхности pygame), чем sys.getsizeof ()
import pygame as pg
import os
import psutil
import time
process = psutil.Process(os.getpid())
pg.init()
vocab = ['hello', 'me', 'you', 'she', 'he', 'they', 'we',
'should', 'why?', 'necessarily', 'do', 'that']
font = pg.font.SysFont("monospace", 100, True)
dct = {}
newMem = process.memory_info().rss # don't mind this line
Str = f'store ' + f'Nothing \tsurface use about '.expandtabs(15) + \
f'0\t bytes'.expandtabs(9) # don't mind this assignment too
usedMem = process.memory_info().rss
for word in vocab:
dct[word] = font.render(word, True, pg.Color("#000000"))
time.sleep(0.1) # wait a moment
# get total used memory of this script:
newMem = process.memory_info().rss
Str = f'store ' + f'{word}\tsurface use about '.expandtabs(15) + \
f'{newMem - usedMem}\t bytes'.expandtabs(9)
print(Str)
usedMem = newMem
В моих окнах 10, python 3.7.3 вывод:
store hello surface use about 225280 bytes
store me surface use about 61440 bytes
store you surface use about 94208 bytes
store she surface use about 81920 bytes
store he surface use about 53248 bytes
store they surface use about 114688 bytes
store we surface use about 57344 bytes
store should surface use about 172032 bytes
store why? surface use about 110592 bytes
store necessarily surface use about 311296 bytes
store do surface use about 57344 bytes
store that surface use about 110592 bytes
Добавьте к заявлению об отказе от ответственности, что это не относится к вложенным объектам, вложенным диктовкам или диктовкам в списках и т. д.