Hallo Leute!
habe folgendes Problem: Ich möchte in Python größere Datenmengen Puffern. Meine Fragen hierbei:
1. Welche Größe fasst eine normale Variable in Python? 32 Bit?
2. Welche Größe fasst ein Array/Liste?
3. Wie kann man die Größe eines Arrays bestimmen?
Mir ist klar das man über
var = [1,4,5,66,"dfasfafsf","fasff",3]
print len(var)
die Anzahl der Elemente ermitteln kann, jedoch möchte ich wissen wie viel Speicher konkret im RAM verwendet wird um die Daten zu speichern. Gibt es dafür eine "sizeof" Funktion, die mir den konkreten Speicherbedarf zurückgibt?
Danke für die Unterstützung!
mfg Killigen
Speichergröße ermitteln
@Killigen: Die Frage lässt sich nicht wirklich beantworten.
Was ist eine „normale Variable“? In Python ist jeder Wert ein Objekt. In CPython wird für jedes Objekt eine C-Datenstruktur angelegt/verwendet. Wie gross die letztendlich ist, hängt auch vom System ab, wie viele Bytes dort beispielsweise ganze Zahlen (in C) oder Zeiger belegen und eventuell auch welche Ausrichtungen von Strukturfeldern vom Compiler vorgenommen werden.
Dann stellt sich aber auch die Frage bei Datenstrukturen ob da verschiedene Objekte drinstecken, oder teilweise Objekte mehrfach. Und ob Objekte auch ausserhalb der Datenstruktur ebenfalls verwendet werden. Wie soll so etwas dann bei der Grösse zählen?
Die ”Grundgrösse” eines Objekts kann man mit der `__sizeof__()`-Methode abfragen:
Was ist eine „normale Variable“? In Python ist jeder Wert ein Objekt. In CPython wird für jedes Objekt eine C-Datenstruktur angelegt/verwendet. Wie gross die letztendlich ist, hängt auch vom System ab, wie viele Bytes dort beispielsweise ganze Zahlen (in C) oder Zeiger belegen und eventuell auch welche Ausrichtungen von Strukturfeldern vom Compiler vorgenommen werden.
Dann stellt sich aber auch die Frage bei Datenstrukturen ob da verschiedene Objekte drinstecken, oder teilweise Objekte mehrfach. Und ob Objekte auch ausserhalb der Datenstruktur ebenfalls verwendet werden. Wie soll so etwas dann bei der Grösse zählen?
Die ”Grundgrösse” eines Objekts kann man mit der `__sizeof__()`-Methode abfragen:
Code: Alles auswählen
In [2]: object().__sizeof__()
Out[2]: 8
In [3]: 42 .__sizeof__()
Out[3]: 12
In [4]: 'hallo'.__sizeof__()
Out[4]: 26
@BackJack:
Ich schildere mein genaues Problem: Ich habe eine Klasse. Diese enthält u.a. zwei Attribute (Listen). Von dieser Klasse werden im Programmablauf immer wieder neue Objekte erzeugt. Diese Objekte werden dann wiederum in einer Liste gepuffert. Diese Liste kann nun sehr groß werden. Aus diesem Grund möchte ich wissen welche Größe diese Liste im Speicher einnimmt. Um dem Problem eines RAM- Überlaufs entgegenzuwirken möchte ich die Informationen ab einer bestimmten Größe der Liste in ein externes File schreiben und die Liste dann wieder leeren, um den Speicher wieder freizugeben. Wie setze ich das am Besten um?
Zu der Methode __sizeof__():
Was soll man genau unter dem Begriff Grundgröße verstehen?
Was sagt die Zahl aus die man zurückbekommt? x Bit werden zum Speichern verwendet? Also für das Objekt 42 werden 12 Bit verwendet??? Kommt mir recht viel vor...
Ich schildere mein genaues Problem: Ich habe eine Klasse. Diese enthält u.a. zwei Attribute (Listen). Von dieser Klasse werden im Programmablauf immer wieder neue Objekte erzeugt. Diese Objekte werden dann wiederum in einer Liste gepuffert. Diese Liste kann nun sehr groß werden. Aus diesem Grund möchte ich wissen welche Größe diese Liste im Speicher einnimmt. Um dem Problem eines RAM- Überlaufs entgegenzuwirken möchte ich die Informationen ab einer bestimmten Größe der Liste in ein externes File schreiben und die Liste dann wieder leeren, um den Speicher wieder freizugeben. Wie setze ich das am Besten um?
Zu der Methode __sizeof__():
Was soll man genau unter dem Begriff Grundgröße verstehen?
Was sagt die Zahl aus die man zurückbekommt? x Bit werden zum Speichern verwendet? Also für das Objekt 42 werden 12 Bit verwendet??? Kommt mir recht viel vor...
Es ist viel. Eine simple Zahl ist in Python trotzdem eine komplette PyObject-Struktur in C.
Mir klingt dein Problem eher antizipatorischer Natur. *Hast* du Speicherueberlaufsprobleme, oder glaubst du nur sie zu haben? Und wenn du sie hast, hast du eine Strategie, die besser ist, als das System swappen zu lassen? Nicht, dass das toll waere. Aber wenn du kein Kriterium hast, nach dem du die Daten partitionieren kannst, dann implementier das halt.
Mir klingt dein Problem eher antizipatorischer Natur. *Hast* du Speicherueberlaufsprobleme, oder glaubst du nur sie zu haben? Und wenn du sie hast, hast du eine Strategie, die besser ist, als das System swappen zu lassen? Nicht, dass das toll waere. Aber wenn du kein Kriterium hast, nach dem du die Daten partitionieren kannst, dann implementier das halt.
@Killigen: Wenn Dir 12 Bits schon viel vorkommt, dann möchtest Du vielleicht gar nicht wissen das das *Bytes* sind.
Grundgrösse heisst, das es nur das Objekt selbst betrifft und nicht Elemente oder Attribute. Eine Liste mit n Elementen liefert bei der Methode immer die gleiche Byteanzahl, egal wie viel Speicher die Elemente belegen:
Grundgrösse heisst, das es nur das Objekt selbst betrifft und nicht Elemente oder Attribute. Eine Liste mit n Elementen liefert bei der Methode immer die gleiche Byteanzahl, egal wie viel Speicher die Elemente belegen:
Code: Alles auswählen
In [6]: [] .__sizeof__()
Out[6]: 20
In [7]: [1, 2, 3] .__sizeof__()
Out[7]: 32
In [8]: [1, 2, 'abcdefghijklmnopqrstuvwxyz'] .__sizeof__()
Out[8]: 32
Man sollte auch Bedenken dass alles bisher gesagte nur auf CPython zutrifft. PyPy schaut sich z.B. den Inhalt von Listen und Dicts an und verwendet davon abhängig optimierte Implementationen die weniger Speicher verbrauchen. Dann bleibt aber immer noch der Speicherverbrauch des Interpreters selbst, der schon nicht unerheblich ist.
Wenn man ernsthaft soviel Wert auf den Speicherverbrauch legt, muss man schon seine Sprache dementsprechend wählen. Rust wäre vielleicht eine sinnvolle Wahl.
Wenn man ernsthaft soviel Wert auf den Speicherverbrauch legt, muss man schon seine Sprache dementsprechend wählen. Rust wäre vielleicht eine sinnvolle Wahl.
Also folgendes: Ich habe mich mit Kommilitonen unterhalten und bin zu dem Ergebnis gekommen das Ganze anders aufzuziehen. Und zwar werde ich den Speicherverbrauch meines gesamten Scripts verwenden, um anhand dessen quasi den "Cache" zu leeren. Hier meine Frage nun: Gibt es eine Möglichkeit über in-built Funktionen oder Bibliotheken den aktuellen Speicherverauch des kompletten Scripts zu erhalten?
Danke im Voraus!
Danke im Voraus!
@Killigen: Also man kann den Speicherverbrauch von Prozessen beispielsweise mit dem `psutils`-Modul abfragen, allerdings muss der Speicher der freigegeben wird, nicht zwangsläufig an das Betriebssystem zurückgegeben werden. Es kann also durchaus passieren dass das freigeben von den Objekten keinerlei Einfluss auf den vom Prozess verbrauchten Speicher hat.
Das heißt wenn ich bei einer Überschreitung meiner gedachten Begrenzung die Liste wieder leere kann es sein, dass der Speicherplatz trotzdem weiter belegt ist!? Und wenn ich die Liste im Anschluss erneut befülle wird zusätzlicher RAM benötigt?
@Killigen: Nein, denn Python bzw. die C-Laufzeitbibliothek weiss ja welcher Platz ”belegt” und welcher ”frei” ist. Dieses Konzept kann es halt auf mehreren Ebenen geben: Dem Betriebssystem, der C-Laufzeitbibliothek (`malloc()`/`free()`), und der Python-Laufzeitbibliothek. Und nur an die Informationen vom Betriebssystem kommt man über eine öffentliche Schnittstelle heran (AFAIK).
Es gibt tracemalloc welches mit PEP 454 vorgeschlagen wurde. Das dürfte allerdings hier nur begrenzt hilfreich sein.
- cofi
- Python-Forum Veteran
- Beiträge: 4432
- Registriert: Sonntag 30. März 2008, 04:16
- Wohnort: RGFybXN0YWR0
Um nochmal auf __deets__ zurueckzukommen: Weisst du, ob du ein Speicherproblem hast? Wenn ja, wie sieht das aus?
Speicherschonend zu programmieren ist eine Sache, sich unnoetig Gedanken um ein moegliches Problem zu machen ist eine andere Sache.
Speicherschonend zu programmieren ist eine Sache, sich unnoetig Gedanken um ein moegliches Problem zu machen ist eine andere Sache.
Michael Markert ❖ PEP 8 Übersetzung ❖ Tutorial Übersetzung (3.x) ⇒ Online-Version (Python 3.3) ❖ Deutscher Python-Insider ❖ Projekte