Je cherchais un moyen simple de connaître la taille en octets des tableaux et des objets de dictionnaires, comme
[ [1,2,3], [4,5,6] ] or { 1:{2:2} }
De nombreux sujets disent d'utiliser pylab, par exemple:
from pylab import *
A = array( [ [1,2,3], [4,5,6] ] )
A.nbytes
24
Mais qu'en est-il des dictionnaires? J'ai vu beaucoup de réponses proposant d'utiliser pysize ou heapy. Une réponse simple est donnée par Torsten Marek dans ce lien: Quel Python est recommandé? , mais je n'ai pas d'interprétation claire sur la sortie car le nombre d'octets ne correspondait pas.
Pysize semble être plus compliqué et je n'ai pas encore d'idée claire sur la façon de l'utiliser.
Compte tenu de la simplicité du calcul de la taille que je veux effectuer (pas de classes ni de structures complexes), une idée d'un moyen facile d'obtenir une estimation approximative de l'utilisation de la mémoire de ce type d'objets?
Sincères amitiés.
Il y a:
>>> import sys
>>> sys.getsizeof([1,2, 3])
96
>>> a = []
>>> sys.getsizeof(a)
72
>>> a = [1]
>>> sys.getsizeof(a)
80
Mais je ne dirais pas que c'est aussi fiable, car Python a des frais généraux pour chaque objet, et il y a des objets qui ne contiennent que des références à d'autres objets, donc ce n'est pas tout à fait la même chose qu'en C et autres langues.
Lisez les documents sur sys.getsizeof et allez-y, je suppose.
un peu tard pour la fête, mais un moyen facile d'obtenir la taille du dict est de le décaper en premier.
L'utilisation de sys.getsizeof sur python (dictionnaire compris) peut ne pas être exacte car elle ne compte pas les objets référencés.
La façon de le gérer consiste à le sérialiser en une chaîne et à utiliser sys.getsizeof sur la chaîne. Le résultat sera beaucoup plus proche de ce que vous voulez.
import cPickle
mydict = {'key1':'some long string, 'key2':[some, list], 'key3': whatever other data}
faire sys.getsizeof (mydict) n'est pas exact donc, décapez-le d'abord
mydict_as_string = cPickle.dumps(mydict)
maintenant, nous pouvons savoir combien d'espace il faut
print sys.getsizeof(mydict_as_string)
Aucune des réponses ici n'est vraiment générique.
La solution suivante fonctionnera avec n'importe quel type d'objet de manière récursive, sans avoir besoin d'une implémentation récursive coûteuse:
import gc
import sys
def get_obj_size(obj):
marked = {id(obj)}
obj_q = [obj]
sz = 0
while obj_q:
sz += sum(map(sys.getsizeof, obj_q))
# Lookup all the object referred to by the object in obj_q.
# See: https://docs.python.org/3.7/library/gc.html#gc.get_referents
all_refr = ((id(o), o) for o in gc.get_referents(*obj_q))
# Filter object that are already marked.
# Using dict notation will prevent repeated objects.
new_refr = {o_id: o for o_id, o in all_refr if o_id not in marked and not isinstance(o, type)}
# The new obj_q will be the ones that were not marked,
# and we will update marked with their ids so we will
# not traverse them again.
obj_q = new_refr.values()
marked.update(new_refr.keys())
return sz
Par exemple:
>>> import numpy as np
>>> x = np.random.Rand(1024).astype(np.float64)
>>> y = np.random.Rand(1024).astype(np.float64)
>>> a = {'x': x, 'y': y}
>>> get_obj_size(a)
16816
Voir mon référentiel pour plus d'informations, ou installez simplement mon package ( objsize ):
$ pip install objsize
Ensuite:
>>> from objsize import get_deep_size
>>> get_deep_size(a)
16816
Utilisez cette recette, tirée d'ici:
http://code.activestate.com/recipes/577504-compute-memory-footprint-of-an-object-and-its-cont/
from __future__ import print_function
from sys import getsizeof, stderr
from itertools import chain
from collections import deque
try:
from reprlib import repr
except ImportError:
pass
def total_size(o, handlers={}, verbose=False):
""" Returns the approximate memory footprint an object and all of its contents.
Automatically finds the contents of the following builtin containers and
their subclasses: Tuple, list, deque, dict, set and frozenset.
To search other containers, add handlers to iterate over their contents:
handlers = {SomeContainerClass: iter,
OtherContainerClass: OtherContainerClass.get_elements}
"""
dict_handler = lambda d: chain.from_iterable(d.items())
all_handlers = {Tuple: iter,
list: iter,
deque: iter,
dict: dict_handler,
set: iter,
frozenset: iter,
}
all_handlers.update(handlers) # user handlers take precedence
seen = set() # track which object id's have already been seen
default_size = getsizeof(0) # estimate sizeof object without __sizeof__
def sizeof(o):
if id(o) in seen: # do not double count the same object
return 0
seen.add(id(o))
s = getsizeof(o, default_size)
if verbose:
print(s, type(o), repr(o), file=stderr)
for typ, handler in all_handlers.items():
if isinstance(o, typ):
s += sum(map(sizeof, handler(o)))
break
return s
return sizeof(o)
##### Example call #####
if __== '__main__':
d = dict(a=1, b=2, c=3, d=[4,5,6,7], e='a string of chars')
print(total_size(d, verbose=True))