2012-11-23 2 views
22

Ich war für eine einfache Möglichkeit suchen Bytes Größe von Arrays und Wörterbücher zu wissen Objekt, wieWie kann man die Größe eines Python-Objekts wie Arrays und Wörterbücher verstehen? - Der einfache Weg

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

Viele Themen sagen pylab zu verwenden, zum Beispiel:

from pylab import * 

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

Aber, Was ist mit Wörterbüchern? Ich sah viele Antworten, die vorschlugen, pysize oder heapy zu verwenden. Eine einfache Antwort gibt Torsten Marek in diesem Link: Which Python memory profiler is recommended?, aber ich habe keine klare Interpretation der Ausgabe, weil die Anzahl der Bytes nicht übereinstimmte.

Pysize scheint komplizierter zu sein und ich habe keine klare Vorstellung davon, wie man es noch benutzt.

Angesichts der Einfachheit der Größenberechnung, die ich durchführen möchte (keine Klassen oder komplexe Strukturen), irgendeine Idee über eine einfache Möglichkeit, eine ungefähre Schätzung der Speichernutzung dieser Art von Objekten zu erhalten?

Mit freundlichen Grüßen.

Antwort

31

Es gibt:

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

Aber ich würde nicht sagen, es ist so zuverlässig, als Python-Overhead für jedes Objekt hat, und es gibt Objekte, die nichts anderes als Verweise auf andere Objekte enthalten, so ist es nicht ganz das gleiche wie in C und anderen Sprachen.

Lesen Sie die Dokumente auf sys.getsizeof und gehen Sie von dort aus, denke ich.

+0

Ich versuchte es so, aber wenn Sie versuchen, Größe einer Liste von Listen zu erhalten, erhalten Sie nur die übergeordnete Listengröße und nicht die Summe mit den verschachtelten Listen. Ich weiß nicht, ob ich Code für die Rekursion schreibe, ich bekomme die tatsächliche Speichernutzung. – crandrades

+3

@ user1847706 am Ende des Eintrags, zu dem ich Sie in den Dokumenten verlinkt habe, gibt es [Siehe rekursive sizeof recipe für ein Beispiel für die rekursive Verwendung von gotsizeof(), um die Größe von Containern und ihren gesamten Inhalt zu finden.] (Http: // code .activestate.com/recipes/577504 /) –

+0

Danke für Ihre Antwort. Jetzt versuche ich einen Handler hinzuzufügen, um die Speicherauslastung für eine benutzerdefinierte Klasse zu berechnen. – crandrades

19

ein bisschen spät auf die Party, aber ein einfacher Weg, um die Größe des Diktats zu bekommen, ist es zuerst zu pickle.

Die Verwendung von sys.getsizeof im Python-Objekt (einschließlich Wörterbuch) ist möglicherweise nicht exakt, da referenzierte Objekte nicht gezählt werden.

Der Weg, es zu behandeln, ist, es in eine Zeichenkette zu serialisieren und sys.getsizeof auf der Zeichenkette zu verwenden. Das Ergebnis wird viel näher an dem sein, was Sie wollen.

import cPickle 

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

tun sys.getsizeof (myDict) so nicht exakt ist, Beize es zuerst

mydict_as_string = cPickle.dumps(mydict) 

jetzt können wir wissen, wie viel Platz es durch

print sys.getsizeof(mydict_as_string) 
+3

Dies sagt Ihnen nicht die Größe des Diktats; es wird Ihnen die Größe der Pickle-Repräsentation des Diktats mitteilen, die (möglicherweise um einen beträchtlichen Betrag) größer sein wird als die In-Memory-Größe des Diktats. – jbg

+0

@ JasperBryant-Greene das ist der Punkt. Die Verwendung von sys.getsizeof für das Python-Objekt (einschließlich des Wörterbuchs) ist möglicherweise nicht exakt, da die referenzierten Objekte nicht gezählt werden. Serialisierung und dann die Größe ist nicht genau, aber wird näher sein, was Sie wollen. Betrachten Sie es als eine Annäherung. –

+0

Sicher, aber die Frage fragt nach "eine ungefähre Schätzung der Speichernutzung dieser Art von Objekten". Ich denke, dies ist nicht einmal eine ungefähre Schätzung der Speichernutzung - die eingelegte Größe wird typischerweise viel größer sein. – jbg

7

Verwenden Sie dieses Rezept nimmt, von hier genommen:

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))