2012-11-23 10 views
22

szukałem łatwy sposób poznania bajtów rozmiar tablic i słowników obiektu, jakJak poznać rozmiar bajtów obiektu python, takich jak tablice i słowniki? - Prosty sposób

[ [1,2,3], [4,5,6] ] or { 1:{2:2} } 

Wiele tematów powiedzieć używać pylab, na przykład:

from pylab import * 

A = array([ [1,2,3], [4,5,6] ]) 
A.nbytes 
24 

Ale a co ze słownikami? Widziałem wiele odpowiedzi proponujących użycie pysize lub heapy. Łatwa odpowiedź jest podana przez Torstena Marka pod tym linkiem: Which Python memory profiler is recommended?, ale nie mam jasnej interpretacji wyjścia, ponieważ liczba bajtów nie jest zgodna.

Pysize wydaje się być bardziej skomplikowany i nie mam jasnego pojęcia, jak go jeszcze użyć.

Biorąc pod uwagę prostotę obliczania wielkości, którą chcę wykonać (brak klas ani skomplikowanych struktur), każdy pomysł o łatwy sposób uzyskania przybliżonej oceny wykorzystania pamięci tego rodzaju obiektów?

Z pozdrowieniami.

Odpowiedz

31

Jest:

>>> import sys 
>>> sys.getsizeof([1,2, 3]) 
96 
>>> a = [] 
>>> sys.getsizeof(a) 
72 
>>> a = [1] 
>>> sys.getsizeof(a) 
80 

Ale nie powiedziałbym, że jest to niezawodny, jak Python ma narzutu dla każdego obiektu, a istnieją obiekty, które zawierają jedynie odniesienia do innych obiektów, więc to nie jest to samo jak w C i innych językach.

Czytanie dokumentów na temat sys.getsizeof i idź stąd, jak sądzę.

+0

Próbowałem w ten sposób, ale gdy próbujesz uzyskać rozmiar listy list, otrzymujesz tylko rozmiar listy nadrzędnej, a nie sumę z zagnieżdżonymi listami. Nie wiem, czy piszę kod do rekursji, dostanę prawdziwe wykorzystanie pamięci. – crandrades

+3

@ user1847706 na końcu wpisu, do którego cię przyłączyłem w dokumentach, znajduje się [Zobacz rekursywny format sizeof dla przykładu użycia metody rekursywnie getizeof() w celu znalezienia rozmiaru kontenerów i całej ich zawartości.] (Http: // code .activestate.com/recipes/577504 /) –

+0

Dzięki za odpowiedź. Teraz próbuję dodać program obsługi do obliczenia wykorzystania pamięci dla klasy zdefiniowanej przez użytkownika. – crandrades

19

trochę za późno na imprezę, ale łatwym sposobem na uzyskanie rozmiaru dyktatu jest najpierw go pozbierać.

Użycie sys.getsizeof na obiekcie Pythona (w tym słowniku) może nie być dokładne, ponieważ nie liczy obiektów, do których się odwołuje.

Sposób na obsłużenie go polega na przekształceniu go do postaci ciągu znaków i użyciu ciągu sys.getsizeof. Wynik będzie znacznie bliżej tego, co chcesz.

import cPickle 

mydict = {'key1':'some long string, 'key2':[some, list], 'key3': whatever other data} 

robi sys.getsizeof (mydict) nie jest dokładna tak słone to pierwszy

mydict_as_string = cPickle.dumps(mydict) 

teraz możemy wiedzieć, ile miejsca zajmuje przez

print sys.getsizeof(mydict_as_string) 
+3

To nie powie ci wielkości dyktowania; powie ci rozmiar reprezentacji pikle dyktatury, która będzie większa (potencjalnie o znaczną ilość) niż rozmiar pamięci w dykcie. – jbg

+0

@ JasperBryant-Greene o to chodzi. Używanie sys.getsizeof na obiekcie Pythona (w tym słowniku) może nie być dokładne, ponieważ nie liczy obiektów, do których się odwołuje. Serializowanie go, a następnie uzyskanie rozmiaru nie jest dokładne, ale będzie bliżej tego, co chcesz. Pomyśl o tym jako o przybliżeniu. –

+0

Oczywiście, ale pytanie wymaga "przybliżonej oceny wykorzystania pamięci tego rodzaju obiektów". Myślę, że to nie kwalifikuje się nawet jako przybliżona ocena wykorzystania pamięci - rozmiar piklowany będzie zazwyczaj znacznie większy. – jbg

7

Użyj tego przepisu, pobrane stąd:

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 __name__ == '__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)) 
Powiązane problemy