Ich möchte wissen, wie man die Größe von Objekten wie einer Zeichenfolge, einer Ganzzahl usw. in Python ermittelt.
Verwandte Frage: Wie viele Bytes pro Element enthält eine Python-Liste (Tupel)?
Ich verwende eine XML-Datei, die Größenfelder enthält, die die Größe des Werts angeben. Ich muss dieses XML analysieren und meine Codierung durchführen. Wenn ich den Wert eines bestimmten Feldes ändern möchte, überprüfe ich das Größenfeld dieses Werts. Hier möchte ich vergleichen, ob der neue Wert, den ich eingeben möchte, dieselbe Größe wie in XML hat. Ich muss die Größe des neuen Werts überprüfen. Im Falle einer Zeichenfolge kann ich sagen, dass es die Länge ist. Aber im Falle von int, float usw. bin ich verwirrt.
__sizeof__
Methode für Ihre Klasse definieren. Die eingebautedict
Python-Klasse definiert es, deshalb erhalten Sie das richtige Ergebnis, wenn Sie ein Objekt vom Typ verwendendict
.getsizeof
Funktion von geringem Wert ist.Die Antwort "Verwenden Sie einfach sys.getsizeof" ist keine vollständige Antwort.
Diese Antwort funktioniert direkt für integrierte Objekte, berücksichtigt jedoch nicht, was diese Objekte enthalten können, insbesondere welche Typen wie benutzerdefinierte Objekte, Tupel, Listen, Diktate und Mengen enthalten. Sie können sich gegenseitig Instanzen sowie Zahlen, Zeichenfolgen und andere Objekte enthalten.
Eine vollständigere Antwort
Unter Verwendung von 64-Bit-Python 3.6 aus der Anaconda-Distribution mit sys.getsizeof habe ich die Mindestgröße der folgenden Objekte festgelegt und festgestellt, dass Mengen und Diktate Speicherplatz vorab zuweisen, sodass leere Objekte erst nach einer festgelegten Menge wieder wachsen (was möglicherweise der Fall ist) variieren je nach Implementierung der Sprache):
Python 3:
Wie interpretieren Sie das? Angenommen, Sie haben ein Set mit 10 Artikeln. Wenn jedes Element jeweils 100 Byte umfasst, wie groß ist die gesamte Datenstruktur? Der Satz ist 736 selbst, da er einmal auf 736 Bytes skaliert wurde. Dann addieren Sie die Größe der Elemente, sodass insgesamt 1736 Byte vorhanden sind
Einige Einschränkungen für Funktions- und Klassendefinitionen:
Beachten Sie, dass jede Klassendefinition eine Proxy-
__dict__
Struktur (48 Byte) für Klassenattrs hat. Jeder Slot hat einen Deskriptor (wie aproperty
) in der Klassendefinition.Geschlitzte Instanzen beginnen mit 48 Bytes in ihrem ersten Element und erhöhen sich um jeweils 8 Bytes. Nur leere Objekte mit Schlitz haben 16 Bytes, und eine Instanz ohne Daten macht wenig Sinn.
Außerdem enthält jede Funktionsdefinition Codeobjekte, möglicherweise Dokumentzeichenfolgen, und andere mögliche Attribute, sogar a
__dict__
.Beachten Sie auch, dass wir verwenden,
sys.getsizeof()
weil wir uns um die marginale Speicherplatznutzung kümmern, einschließlich des Speicherbereinigungsaufwands für das Objekt aus den Dokumenten :Beachten Sie auch, dass das Ändern der Größe von Listen (z. B. das wiederholte Anhängen an Listen) dazu führt, dass sie Speicherplatz vorab zuweisen, ähnlich wie bei Sätzen und Diktaten. Aus dem Quellcode listobj.c :
Historische Daten
Python 2.7-Analyse, bestätigt mit
guppy.hpy
undsys.getsizeof
:Beachten Sie, dass Wörterbücher ( aber keine Mengen ) in Python 3.6 eine kompaktere Darstellung erhalten
Ich denke, 8 Bytes pro zusätzlichem Referenzelement sind auf einem 64-Bit-Computer sehr sinnvoll. Diese 8 Bytes zeigen auf die Stelle im Speicher, an der sich das enthaltene Element befindet. Die 4 Bytes haben eine feste Breite für Unicode in Python 2, wenn ich mich richtig erinnere, aber in Python 3 wird str zu einem Unicode mit einer Breite, die der maximalen Breite der Zeichen entspricht.
(Weitere Informationen zu Slots finden Sie in dieser Antwort. )
Eine vollständigere Funktion
Wir wollen eine Funktion, die die Elemente in Listen, Tupeln, Mengen, Diktaten
obj.__dict__
, undobj.__slots__
anderen Dingen durchsucht, an die wir vielleicht noch nicht gedacht haben.Wir möchten
gc.get_referents
uns bei dieser Suche darauf verlassen, dass sie auf C-Ebene funktioniert (was sie sehr schnell macht). Der Nachteil ist, dass get_referents redundante Mitglieder zurückgeben kann. Daher müssen wir sicherstellen, dass wir nicht doppelt zählen.Klassen, Module und Funktionen sind Singletons - sie existieren einmal im Speicher. Wir sind nicht so an ihrer Größe interessiert, da wir nicht viel gegen sie tun können - sie sind Teil des Programms. Wir vermeiden es also, sie zu zählen, wenn auf sie verwiesen wird.
Wir werden eine schwarze Liste von Typen verwenden, damit wir nicht das gesamte Programm in unsere Größenanzahl einbeziehen.
Um dies mit der folgenden Whitelist-Funktion zu vergleichen, wissen die meisten Objekte, wie sie sich zum Zwecke der Speicherbereinigung selbst durchlaufen müssen (was ungefähr das ist, wonach wir suchen, wenn wir wissen möchten, wie teuer bestimmte Objekte im Speicher sind. Diese Funktionalität wird von verwendet
gc.get_referents
.) Diese Maßnahme wird jedoch einen viel größeren Umfang haben, als wir beabsichtigt hatten, wenn wir nicht vorsichtig sind.Zum Beispiel wissen Funktionen ziemlich viel über die Module, in denen sie erstellt werden.
Ein weiterer Kontrastpunkt ist, dass Zeichenfolgen, die Schlüssel in Wörterbüchern sind, normalerweise interniert werden, damit sie nicht dupliziert werden. Durch das Überprüfen auf
id(key)
können wir auch vermeiden, dass Duplikate gezählt werden, was wir im nächsten Abschnitt tun. Die Blacklist-Lösung überspringt das Zählen von Schlüsseln, die insgesamt Zeichenfolgen sind.Whitelisted-Typen, rekursiver Besucher (alte Implementierung)
Um die meisten dieser Typen selbst abzudecken, habe ich diese rekursive Funktion geschrieben, anstatt zu versuchen, die Größe der meisten Python-Objekte zu schätzen, einschließlich der meisten integrierten Funktionen, Typen im Sammlungsmodul und benutzerdefinierter Typen (mit und ohne Slots). .
Diese Art von Funktion bietet eine viel feinere Kontrolle über die Typen, die für die Speichernutzung gezählt werden sollen, birgt jedoch die Gefahr, dass Typen weggelassen werden:
Und ich habe es eher beiläufig getestet (ich sollte es nicht testen):
Diese Implementierung gliedert sich in Klassendefinitionen und Funktionsdefinitionen, da wir nicht alle ihre Attribute verfolgen. Da sie jedoch nur einmal im Speicher für den Prozess vorhanden sein sollten, spielt ihre Größe keine große Rolle.
quelle
Das Modul des Pympler- Pakets
asizeof
kann dies tun.Verwenden Sie wie folgt:
Im Gegensatz
sys.getsizeof
dazu funktioniert es für Ihre selbst erstellten Objekte . Es funktioniert sogar mit Numpy.Wie bereits erwähnt ,
Und wenn Sie eine andere Ansicht von Live-Daten benötigen, Pympler's
quelle
org.apache.spark.util.SizeEstimator
kann aber relevant seinpympler
es Funktionen zur Berücksichtigung der Größe des ausführbaren Codes von Funktionen und anderen aufrufbaren Elementen und Codeobjekten bietet.TypeError
Ausnahme: "'NoneType'-Objekt ist nicht aufrufbar", wenn mein benutzerdefiniertes Objekt in seinem "Baum" ein Unterobjekt mit Wert enthältNone
. Gibt es dafür eine schnelle Problemumgehung?Bei numpy Arrays
getsizeof
funktioniert das nicht - bei mir wird aus irgendeinem Grund immer 40 zurückgegeben:Dann (in ipython):
Zum Glück:
quelle
getsizeof()
gibt jedoch nur die Größe des Objekts (den Header des Arrays) an, nicht die darin enthaltenen Daten. Gleiches gilt für Python-Containersys.getsizeof([1,2,4]) == sys.getsizeof([1,123**456,4]) == 48
, bei denensys.getsizeof(123**456) = 436
getsizeof()
Funktion irgendwann geändert wurde, um den erwarteten Wert zurückzugeben.Dies kann komplizierter sein, als es aussieht, je nachdem, wie Sie die Dinge zählen möchten. Wenn Sie beispielsweise eine Liste von Ints haben, möchten Sie die Größe der Liste, die die Verweise auf die Ints enthält? (dh nur eine Liste, nicht das, was darin enthalten ist), oder möchten Sie die tatsächlichen Daten einschließen, auf die verwiesen wird? In diesem Fall müssen Sie sich mit doppelten Referenzen befassen und wie Sie eine Doppelzählung verhindern, wenn zwei Objekte Verweise auf enthalten das gleiche Objekt.
Vielleicht möchten Sie einen Blick auf einen der Python-Speicherprofiler werfen , z. B. Pysizer , um festzustellen , ob diese Ihren Anforderungen entsprechen.
quelle
Python 3.8 (Q1 2019) wird einige der Ergebnisse von ändern
sys.getsizeof
, wie hier von Raymond Hettinger angekündigt :Dies geschieht nach Ausgabe 33597 und Inada Naokis (
methane
) Arbeit um Compact PyGC_Head und PR 7043Siehe Commit d5c875b :
quelle
Nachdem ich selbst oft auf dieses Problem gestoßen war, schrieb ich eine kleine Funktion (inspiriert von der Antwort von @ aaron-hall) und Tests, die das tun, was ich von sys.getsizeof erwartet hätte:
https://github.com/bosswissam/pysize
Wenn Sie an der Hintergrundgeschichte interessiert sind, hier ist sie
BEARBEITEN: Fügen Sie den folgenden Code zur leichteren Bezugnahme hinzu. Um den aktuellsten Code zu sehen, überprüfen Sie bitte den Github-Link.
quelle
Hier ist ein kurzes Skript, das ich basierend auf den vorherigen Antworten auf die Listengrößen aller Variablen geschrieben habe
quelle
Sie können das Objekt serialisieren, um ein Maß abzuleiten, das eng mit der Größe des Objekts zusammenhängt:
Wenn Sie Objekte messen möchten, die nicht eingelegt werden können (z. B. aufgrund von Lambda-Ausdrücken), kann Cloudpickle eine Lösung sein.
quelle
Verwenden Sie sys.getsizeof (), wenn Sie die Größe verknüpfter (verschachtelter) Objekte NICHT einschließen möchten.
Wenn Sie jedoch Unterobjekte zählen möchten, die in Listen, Diktaten, Mengen, Tupeln verschachtelt sind - und normalerweise ist dies das, wonach Sie suchen -, verwenden Sie die rekursive Funktion deep sizeof () wie folgt :
Sie finden diese Funktion zusammen mit vielen anderen nützlichen Einzeilern auch in der raffinierten Toolbox:
https://github.com/mwojnars/nifty/blob/master/util.py
quelle
Wenn Sie nicht die genaue Größe des Objekts benötigen, aber ungefähr wissen möchten, wie groß es ist, können Sie das Programm schnell (und schmutzig) laufen lassen, über einen längeren Zeitraum in den Ruhezustand versetzen und die Speichernutzung überprüfen (z : Macs Aktivitätsmonitor) durch diesen speziellen Python-Prozess. Dies ist effektiv, wenn Sie versuchen, die Größe eines einzelnen großen Objekts in einem Python-Prozess zu ermitteln. Zum Beispiel wollte ich kürzlich die Speichernutzung einer neuen Datenstruktur überprüfen und mit der von Pythons festgelegter Datenstruktur vergleichen. Zuerst schrieb ich die Elemente (Wörter aus einem großen gemeinfreien Buch) in eine Menge, überprüfte dann die Größe des Prozesses und tat dann dasselbe mit der anderen Datenstruktur. Ich habe herausgefunden, dass der Python-Prozess mit einem Satz doppelt so viel Speicher benötigt wie die neue Datenstruktur. Wieder würden Sie nicht ' Ich kann nicht genau sagen, dass der vom Prozess verwendete Speicher der Größe des Objekts entspricht. Wenn die Größe des Objekts groß wird, wird dies eng, da der vom Rest des Prozesses verbrauchte Speicher im Vergleich zur Größe des Objekts, das Sie überwachen möchten, vernachlässigbar wird.
quelle
Sie können getSizeof () wie unten erwähnt verwenden, um die Größe eines Objekts zu bestimmen
quelle
Ich benutze diesen Trick ... Kann bei kleinen Objekten nicht genau sein, aber ich denke, es ist viel genauer für ein komplexes Objekt (wie eine Pygame-Oberfläche) als für sys.getsizeof ()
Unter Windows 10, Python 3.7.3, lautet die Ausgabe:
quelle