2012-11-23 11 views
22

ero alla ricerca di un modo semplice per sapere byte dimensioni array e dizionari oggetto, comeCome conoscere la dimensione in byte dell'oggetto python come array e dizionari? - Il modo più semplice

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

Molti argomenti indicano di usare pylab, ad esempio:

from pylab import * 

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

Ma, che dire dei dizionari? Ho visto molte risposte che proponevano di utilizzare pysize o heapy. Torsten Marek fornisce una risposta semplice a questo collegamento: Which Python memory profiler is recommended?, ma non ho una chiara interpretazione dell'output perché il numero di byte non corrisponde.

Pysize sembra essere più complicato e non ho una chiara idea su come usarlo ancora.

Data la semplicità del calcolo delle dimensioni che voglio eseguire (nessuna classe o struttura complessa), qualche idea su un modo semplice per ottenere una stima approssimativa dell'utilizzo della memoria di questo tipo di oggetti?

Cordiali saluti.

risposta

31

C'è:

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

Ma non direi che è che affidabile, come Python ha in testa per ogni oggetto, e ci sono oggetti che contengono nulla, ma riferimenti ad altri oggetti, quindi non è proprio la stessa cosa come in C e altre lingue.

Avere una lettura dei documenti su sys.getsizeof e andare da lì credo.

+0

Ho provato in questo modo, ma quando si tenta di ottenere la dimensione di un elenco di liste, si ottiene solo la dimensione dell'elenco principale e non il totale con gli elenchi annidati. Non so se scrivo codice per fare la ricorsione, otterrò l'uso della memoria reale. – crandrades

+3

@ user1847706 alla fine della voce in cui ti ho collegato ai documenti, c'è [Vedi la ricetta di sizeof ricorsiva per un esempio di utilizzo di getsizeof() in modo ricorsivo per trovare la dimensione dei contenitori e tutti i loro contenuti.] (Http: // code .activestate.com/recipes/577504 /) –

+0

Grazie per la risposta. Ora, sto cercando di aggiungere un gestore per calcolare l'utilizzo della memoria per una classe definita dall'utente. – crandrades

19

un po 'in ritardo per la festa, ma un modo semplice per ottenere dimensioni di dict è di metterlo sott'aceto prima.

L'utilizzo di sys.getsizeof sull'oggetto python (incluso il dizionario) potrebbe non essere esatto poiché non conteggia gli oggetti di riferimento.

Il modo per gestirlo è serializzarlo in una stringa e utilizzare sys.getsizeof sulla stringa. Il risultato sarà molto più vicino a quello che vuoi.

import cPickle 

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

fare sys.getsizeof (mydict) non è esatto, in modo, salamoia per primo

mydict_as_string = cPickle.dumps(mydict) 

ora possiamo sapere quanto spazio ci vuole per

print sys.getsizeof(mydict_as_string) 
+3

Questo non ti dirà la dimensione del dict; ti dirà la dimensione della rappresentazione sottaceto del dict, che sarà più grande (potenzialmente di una quantità considerevole) rispetto alla dimensione in memoria del dict. – jbg

+0

@ JasperBryant-Greene è questo il punto. L'uso di sys.getsizeof sull'oggetto python (incluso il dizionario) potrebbe non essere esatto poiché non conteggia gli oggetti di riferimento. La serializzazione e la dimensione non sono esatte ma saranno più vicine a ciò che desideri. Pensa ad esso come un'approssimazione. –

+0

Certo, ma la domanda richiede "una stima approssimativa dell'uso della memoria di questo tipo di oggetti". Penso che questo non valga nemmeno come stima approssimativa dell'uso della memoria: le dimensioni in salamoia saranno in genere molto più grandi. – jbg

7

Utilizzare questa ricetta, tratto da qui:

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