clear-Befehl wie in Matlab??

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Zeddelsche
User
Beiträge: 6
Registriert: Freitag 28. September 2007, 07:10

Hallo,

ich habe eine ganz einfache Frage:

Gibt es in Python einen clear-Befehl, wie in Matlab, der mir den Speicher löscht?


Gruß,
Michael
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

Wozu benötigst du so etwas?

Python hat einen Garbage Collector, der automatisch nicht benötigte Objekte aus dem Speichern entfernt -- und der tut seine Arbeit recht gut.

MfG EnTeQuAk
alan
User
Beiträge: 81
Registriert: Dienstag 10. April 2007, 11:30

Vielleicht willst du ja auf irgendeine krude Art und Weise dein Programm reinitialisieren?

Ich mach das so, dass ich einfach die __init__-Methode der entsprechenden Klasse nochmal aufrufe. Oder du erzeugst einfach eine neue Instanz.

Du brauchst dazu allerdings auch ne Klasse :wink:
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Mich würde auch interessieren, was Du eigentlich vorhast? Vielleicht können wir Dir ja einen etwas pythonischeren Weg weisen?

Gruß,
Christian
poker
User
Beiträge: 146
Registriert: Donnerstag 20. September 2007, 21:44

EnTeQuAk hat geschrieben: Python hat einen Garbage Collector, der automatisch nicht benötigte Objekte aus dem Speichern entfernt -- und der tut seine Arbeit recht gut.
...aber nicht gut genug. Pythons GC ist sehr primitiv. Er basiert auf einer Referenzzählung das die primitivste Implementierung eines GC`s darstellt und dessen nachteil eben ist, das es nicht mit zyklischen Referenzen umgehen kann!! Ruby dagegen verwendet einen richtigen Mark-and-Sweep-Algorithmus.

Im "normalen" Alltagsbetrieb hat man wohl kaum "selber" mit zyklischen Referenzen zu tun, aber sobald man einen Parser schreibt der Eingabe X nach Y überführt, wobei y ein Graph ist dessen Nodes kreisförmig aufeinander referenzieren, hat man ein großes Problem mit Speicherlecks! -- Umgehen kann man das ein wenig mit Hilfe von``weakref.proxy`` (Kreisförmige Referenzen werden über schwache Referenzen realisiert.)

IMO gehört das zu einer der größten schwächen von Python.

Interessierte sollte sich mal diesen link durchlesen, wobei ich die Meinung des Autors nicht vollständig teile, betreffend seiner Ansichten zu zyklischen Referenzen, das Mark-and-Sweep[1] "momentan" nicht implementierbar ist für Python ... Aber es liefert einen einblick wie Python da intern arbeitet. BTW: Ja der Artikel ist von 2000 aber IMO hat sich diesbezüglich bei Python nicht viel getan.

[1]:
Unfortunately this approach cannot be used in the current version of Python. Because of the way extension modules work, Python can never fully determine the root set. If the root set cannot be determined accurately we risk freeing objects still referenced from somewhere. Even if extension modules were designed differently, the is no portable way of finding what objects are currently on the C stack...
Hmm! Hört sich genauso an wie der scheiß den GvR zum Thema tail call optimization gesagt hat :roll: Rubys Object-System kann man nicht gerade als primitiv bezeichnen (Der ist dem von Python in einigen dingen sogar überlegen) und da funktioniert der Mark-and-Sweep auch wunderbar (Ja, auch mit C extensions hat Ruby diesbezügliche keine Probleme).


@Zeddelsche:
Sorg dafür das kein Name mehr auf das betreffende Objekt referenziert und der GC springt da bei Gelegenheit[1] an und macht den Speicher frei. Wenn es um sehr viele Objekte geht die z.B. in einem Attribut X (z.B. eine Liste) einer Klasse gekapselt sind, und du ausschließen kannst das die darin befindlichen nirgendswo sonst an einem namen gebunden sind, genügt es einfach ``x=[]`` zu schreiben.

[1]: Gelegentlich deshalb, das es nicht vorhersehbar ist wann der GC den allokierten Speicherbereiche wider freigibt. Das kann der GC machen wennimmer er "Zeit" hat, aber muss es spätestens wenn der Speicher Aufgebraucht wird. -- Das einzige das IMO gewährleistet ist, das der Speicher von Funktions lokalen nach austritt freigegeben wird (Solange unter den lokalen keine Kreisförmige Referenz herrscht. Die werden wie gesagt nie freigegeben).
BlackJack

Python's GC kann auch Objekte mit zirkulären Referenzen freigeben. Ausnahme sind Kreise mit Objekten die eine `__del__()`-Methode besitzen, weil es da keinen Weg gibt zu entscheiden welches Objekt sicher als erstes entfernt werden kann.

Da man `__del__()` sowieso nicht vernünftig benutzen kann, weil so gut wie keine Garantien gemacht werden, wann und ob die Methode aufgerufen wird, sollten solche Kreise eher selten sein.
Zeddelsche
User
Beiträge: 6
Registriert: Freitag 28. September 2007, 07:10

Guten Morgen,

ich schreibe ein Programm in PythonWin und ändere beim Programmieren natürlich auch ständig den Code. estern ist es mir dann passiert, das ich eine Variable im Programm auskommentiert habe, da ich diese momentan nicht brauchte. Beim Programmablauf gab es dann aber Probleme, da die Variable noch im Speicher stand.
Matlab verhält sich hier ähnlich. Wenn man ein m-File ausführt werden alle Variablen in den Speicher geschrieben. Führt man ein anderes m-File aus, dann stehen die alten Variablen immer noch im Speicher. Um hier einen sauberen Schnitt zu machen, gibt es den Befehl clear(). Diesen fügt man einfach am Programmanfang ein und stellt damit sicher, dass sich nichts mehr im Speicher befindet.

So eine Funktion müsste es doch auch in Python geben, oder?

Gruß, Michael
BlackJack

Das ist dann eher eine Frage der IDE oder Umgebung in der Du das laufen lässt und nicht von Python selbst. Bei IPython gibt es zum Beispiel in der Tat einen `clear`-Befehl für die Ein-/Ausgabe-History und einen `reset`-Befehl, der die benutzerdefinierten Namen entfernt.

Wenn Dich nur dieser eine Name stört, dann kannst Du ihn mit ``del name`` entfernen.

Grundsätzlich solltest Du aber Dein Arbeitsmodell überdenken und geänderten Code nicht in einer Umgebung ausführen, in der immer noch Reste von alten Läufen herumliegen könnten. Der interaktive Interpreter ist gut um mal etwas auszuprobieren, aber für Programmläufe sollte man schon eigene Skripte schreiben.
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

Zeddelsche hat geschrieben:ich schreibe ein Programm in PythonWin und ändere beim Programmieren natürlich auch ständig den Code. estern ist es mir dann passiert, das ich eine Variable im Programm auskommentiert habe, da ich diese momentan nicht brauchte. Beim Programmablauf gab es dann aber Probleme, da die Variable noch im Speicher stand.
Hast du den Code während eines Debugs geändert und dann weiterlaufen lassen? Das würde das Verhalten erklären.
Zeddelsche
User
Beiträge: 6
Registriert: Freitag 28. September 2007, 07:10

Nein, nicht während eines Debugs...
BlackJack

Also der Normalfall ist, dass Python-Programme mit einem "leeren Speicher" anfangen, da braucht man nicht extra einen Befehl für. Ich kenne PythonWin nicht, aber auch da sollte es möglich sein Programme richtig zu starten, und nicht in einem Namensraum auszuführen, der vorher schon einmal benutzt wurde.

Das ist also keine Python-Frage, sondern eine Deiner IDE.
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

poker hat geschrieben:
EnTeQuAk hat geschrieben: Python hat einen Garbage Collector, der automatisch nicht benötigte Objekte aus dem Speichern entfernt -- und der tut seine Arbeit recht gut.
...aber nicht gut genug. Pythons GC ist sehr primitiv. Er basiert auf einer Referenzzählung das die primitivste Implementierung eines GC`s darstellt und dessen nachteil eben ist, das es nicht mit zyklischen Referenzen umgehen kann!!
Da hast du wohl was falsch verstanden. Das, was im Kontext von CPython als "GC" bezeichnet wird, ist der in IIRC 2.0 neue Cyclic Garbage Collector, der eben genau deswegen eingeführt wurde, weil zyklische Referenzen vorher Probleme machten.
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

birkenfeld hat geschrieben:Das, was im Kontext von CPython als "GC" bezeichnet wird, ist der in IIRC 2.0 neue Cyclic Garbage Collector, der eben genau deswegen eingeführt wurde, weil zyklische Referenzen vorher Probleme machten.
Deswegen steht der Artikel auf der Übersichtsseite unter Obsolete und der Patch ist für Python 1.5.2. Schade nur, dass das im Artikel nicht steht, dass die Informationen veraltet sind.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
poker
User
Beiträge: 146
Registriert: Donnerstag 20. September 2007, 21:44

BlackJack hat geschrieben:Python's GC kann auch Objekte mit zirkulären Referenzen freigeben. Ausnahme sind Kreise mit Objekten die eine `__del__()`-Methode besitzen, weil es da keinen Weg gibt zu entscheiden welches Objekt sicher als erstes entfernt werden kann.
Nein, nicht wenn er nur auf einer Referenzzählung im "Klassischen" (Erreichbarkeitsproblem im Graphen ignoriert wird.) Sinn basiert. Das liegt halt in der Natur der Sache. Es gibt aber Methoden um auch mit einem auf Referenzzählung basierenden GCs soweit aufzubohren das es Funktioniert, was IMO aber nirgendwo explizite erwähnt wurde.
birkenfeld hat geschrieben: Da hast du wohl was falsch verstanden. Das, was im Kontext von CPython als "GC" bezeichnet wird, ist der in IIRC 2.0 neue Cyclic Garbage Collector, der eben genau deswegen eingeführt wurde, weil zyklische Referenzen vorher Probleme machten.
Ah, schön zu hören :) Das heißt das es nun Quasi zwei GCs in Python gibt oder der alte aufgebohrt wurde um das Erreichbarkeitsproblem im Graphen zu behandeln? Weil, der eigentliche GC basiert doch immer noch auf einer Referenzzählung, was man auch in den Python Extensions sehen kann (XINCREF, XDECREF).

Hättest du vielleicht einen Link bezüglich des GCs von Python, wo die Funktionsweise genau spezifiziert ist?

@Leonidas: Jo, hätte ich vorher mal schauen müssen. Aber, hab den Link schon so langen in meinen Bookmarks, gehe auch in erster Linie davon aus, das Artikel die obsolet sind auch als solche gegenzeichnet werden im Artikel und habe es daher nicht gemacht.


EDIT:
@birkenfeld
Mal "eine" Frage, da du ja ein Dev im Core Team bist:
1. Warum hat man sich gegen einen Mark-and-Sweep entschieden bzw. nicht in betrachte gezogen? Die von mir im ersten Post Zitierte Begründung kann es doch irgendwie nicht sein.
2. Ist für Py3K eine Reformierung des Python GCs geplant? Eventuell Mark-and-Sweep :D
BlackJack

Ich würde sagen es gibt einen GC. Den Mechanismus mit den Referenzzählern sehe ich irgendwie nicht als GC an.

Ich glaube aber Du hast das Problem mit der `__del__()`-Methode nicht ganz erfasst. Innerhalb dieser Methode kann man ja auf die anderen Objekte im Kreis zugreifen. Ein sicheres Entfernen setzt also voraus, dass man entscheiden kann welches Objekt das *nicht* tut und damit als erstes entfernt werden kann. Von dem pathologischen Fall das es *alle* Objekte im Kreis tun und keines sicher als erstes entfernt werden kann, mal ganz abgesehen. Diese Entscheidung kann man bei so einer dynamischen Sprache wie Python einfach nicht automatisiert entscheiden.
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

birkenfeld hat geschrieben: Da hast du wohl was falsch verstanden. Das, was im Kontext von CPython als "GC" bezeichnet wird, ist der in IIRC 2.0 neue Cyclic Garbage Collector, der eben genau deswegen eingeführt wurde, weil zyklische Referenzen vorher Probleme machten.
Ah, schön zu hören :) Das heißt das es nun Quasi zwei GCs in Python gibt oder der alte aufgebohrt wurde um das Erreichbarkeitsproblem im Graphen zu behandeln? Weil, der eigentliche GC basiert doch immer noch auf einer Referenzzählung, was man auch in den Python Extensions sehen kann (XINCREF, XDECREF).
[/quote]
Ja, reference counting ist das hauptsächliche memory management. Der zyklische GC springt nur von Zeit zu Zeit an und kümmert sich um zirkuläre Referenzen.
Hättest du vielleicht einen Link bezüglich des GCs von Python, wo die Funktionsweise genau spezifiziert ist?
Nein, auf die Schnelle nicht. Es müsste sich allerdings in den python-dev-Archiven einiges finden lassen aus der Zeit, in der der GC eingebaut wurde (um 2000 herum).
Mal "eine" Frage, da du ja ein Dev im Core Team bist:
1. Warum hat man sich gegen einen Mark-and-Sweep entschieden bzw. nicht in betrachte gezogen? Die von mir im ersten Post Zitierte Begründung kann es doch irgendwie nicht sein.
Da ich damals nicht dabei war, kann ich nur vermuten: Reference counting funktioniert soweit ja einwandfrei und schnell. Es ermöglicht deterministische Destruktion, wenn man alle Referenzen kennt. Das Hinzufügen des zyklischen GC war wahrscheinlich auch wesentlich einfacher, als das gesamte memory management auszutauschen.
2. Ist für Py3K eine Reformierung des Python GCs geplant? Eventuell Mark-and-Sweep :D
Nein, solange keiner wirkliche Gründe und einen Patch liefert.
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
poker
User
Beiträge: 146
Registriert: Donnerstag 20. September 2007, 21:44

@birkenfeld
Ich danke dir recht herzlich für diese aufschlussreichen Informationen, die meinen alten Wissenstand zu recht gerückt haben. :) Das Archeiv von 2000 werde ich bei Zeit durchforsten.
BlackJack hat geschrieben:Den Mechanismus mit den Referenzzählern sehe ich irgendwie nicht als GC an.
Sonder was soll es sonst sein?
BlackJack hat geschrieben: Ich glaube aber Du hast das Problem mit der `__del__()`-Methode nicht ganz erfasst.
Das kann natürlich sein.

Aber die Dokumentation bezüglich ``__del__`` und des GCs kenne ich ja schon sehr lange ...
BlackJack hat geschrieben: Innerhalb dieser Methode kann man ja auf die anderen Objekte im Kreis zugreifen. Ein sicheres Entfernen setzt also voraus, dass man entscheiden kann welches Objekt das *nicht* tut und damit als erstes entfernt werden kann. Von dem pathologischen Fall das es *alle* Objekte im Kreis tun und keines sicher als erstes entfernt werden kann, mal ganz abgesehen. Diese Entscheidung kann man bei so einer dynamischen Sprache wie Python einfach nicht automatisiert entscheiden.
... aber ich hab das nicht für einen Grund angesehen der es unmöglich macht einen Mark-and-Sweep zu implementieren. Aber deine Ausführung klingt logisch, und das könnte IMO ein grund sein weshalb es in Ruby geht, da es da sowas nicht wie eine ``__del__`` Methode gibt (Nicht das ich wüsste).

Nochmals vielen dank an euch beiden, das ihr mir meine Fragen beantwortet habt.
Antworten