HOWTO · Python

Determinare la dimensione di un oggetto in Python

Questo tutorial discute come determinare la dimensione di un oggetto in Python.

In questa pagina

Usa sys.getsizeof() per ottenere la dimensione superficiale di un oggetto in byte. Il risultato non include le dimensioni degli oggetti a cui quell’oggetto fa riferimento. Per una stima ricorsiva di un contenitore e dei suoi elementi, usa Pympler; per confrontare nel tempo le allocazioni Python, usa tracemalloc.

Misurare la dimensione superficiale di un oggetto con sys.getsizeof()

Importa sys e passa a sys.getsizeof() il valore che vuoi esaminare. L’intero restituito indica la dimensione superficiale dell’oggetto in byte. Per esempio, comprende l’oggetto lista in sé, ma non gli oggetti contenuti nella lista. La distinzione è importante quando un contenitore fa riferimento a stringhe lunghe, altri contenitori annidati o dati di altro tipo.

Esegui questo esempio per misurare un contenitore integrato. Il valore in byte stampato è una lettura illustrativa ottenuta in un ambiente specifico: dipende dall’implementazione e dalla versione di Python e non è un valore fisso valido ovunque:

Il codice e le etichette o gli output visibili in questa sezione restano in inglese.

import sys

values = [10, 20, 30]
size_bytes = sys.getsizeof(values)
print(f"Shallow size: {size_bytes} bytes")
Shallow size: 88 bytes

Puoi passare allo stesso modo altri valori, come una stringa, un intero o un dizionario. Anche le dimensioni riportate per questi valori possono variare tra implementazioni e versioni di Python. Considera il risultato una misura legata all’implementazione, non una garanzia sulla memoria totale del processo né sul costo di tutti gli oggetti raggiungibili a partire dal valore. Nel blocco di output invariato, l’etichetta bytes resta in inglese e il valore mostrato è soltanto un esempio.

Includere gli oggetti referenziati con Pympler

Se ti serve una stima che includa gli oggetti raggiungibili attraverso un contenitore, l’utilità asizeof di Pympler può calcolare ricorsivamente la dimensione degli oggetti referenziati. Installa il pacchetto di terze parti con pip install pympler, quindi importa asizeof da pympler e chiamalo sul valore che vuoi esaminare.

Dopo aver installato Pympler, esegui questo esempio autonomo:

Il codice e le etichette o gli output visibili in questa sezione restano in inglese.

try:
    from pympler import asizeof
except ImportError:
    print("Install Pympler with: pip install pympler")
else:
    values = [1, 2, [3, 4]]
    print(f"Recursive size: {asizeof.asizeof(values)} bytes")

Il numero riportato dipende dall’implementazione e dalla versione di Python, oltre che dalla versione installata di Pympler. Consideralo quindi una stima per questo grafo di oggetti, non un valore fisso valido ovunque.

Questa stima ricorsiva risponde a una domanda diversa da sys.getsizeof(): include gli oggetti annidati, mentre quest’ultimo considera soltanto la dimensione superficiale dell’oggetto esterno. Rimane una stima del grafo di oggetti, non una misura dell’intero processo Python, dell’overhead dell’allocatore o della memoria residente riportata dal sistema operativo. I riferimenti condivisi e i dettagli dell’implementazione possono influire sul modo in cui uno strumento ricorsivo conteggia gli oggetti. Usalo quindi per confrontare le strutture in modo coerente, non come misura esatta della memoria totale del processo.

Tracciare le allocazioni di memoria con tracemalloc

Usa il modulo della libreria standard tracemalloc per osservare le allocazioni di memoria Python effettuate durante una parte del programma. Avvia il tracciamento prima dell’operazione che ti interessa, leggi le dimensioni attuale e di picco tracciate in byte e, al termine, interrompi il tracciamento. L’esempio autonomo seguente alloca una lista mentre il tracciamento è attivo e riporta entrambe le letture; i valori visualizzati sono esempi ottenuti in un ambiente specifico e variano in base all’implementazione di Python e all’ambiente di esecuzione.

Il codice e le etichette o gli output visibili in questa sezione restano in inglese.

import tracemalloc

tracemalloc.start()
values = [number for number in range(1000)]
current_bytes, peak_bytes = tracemalloc.get_traced_memory()
print(f"Current traced memory: {current_bytes} bytes")
print(f"Peak traced memory: {peak_bytes} bytes")
tracemalloc.stop()
Current traced memory: 29536 bytes
Peak traced memory: 29536 bytes

current_bytes indica la quantità attualmente tracciata, mentre peak_bytes è la quantità massima tracciata dall’inizio del tracciamento. Per registrare un’allocazione, il tracciamento deve essere già attivo. Le letture riguardano le allocazioni Python tracciate, non la dimensione ricorsiva conservata da un singolo oggetto scelto. Per capire dove avvengono le allocazioni, usa snapshot oppure confronta le letture in momenti significativi. Quando hai terminato la misurazione, interrompi il tracciamento per evitare che continui a raccogliere dati. Le etichette del blocco di output invariato restano in inglese.