Mal abgesehen davon ob nun ein memoryleak existiert oder nicht:
Wie lange arbeitet man wohl mit einem GUI Designer am Stück?!? Wie viel Elemente erstellt man und verwirft sie wieder?
Ich bekomme es ohne eval nicht hin
@Alfons Mittelmeyer: Doch ich habe richtig gelesen und das ich ein Synonym, das in der Graphentheorie geräuchlicher ist, statt der wortwörtlichen Übersetzung des Wortes „circular” verwendet habe, zeigt das ich den Inhalt der Dokumentation verstanden habe und ihn nicht nur 1:1 wiedergeben kann, sondern auch sinnerhaltend mit anderen Worten. Was normalerweise ein gutes Zeichen ist um zu sehen ob jemand etwas wirklich verstanden hat, oder nur etwas vorgebenes aufsagt ohne es zwingend verstanden zu haben.
Natürlich wird man bei einer `pop()`-Implementierung einer doppelt verketteten Liste den Zyklus in der Referenzierung aufbrechen *müssen*. Es geht um so etwas:
Hierbei würden mindestens zwei Zyklen erhalten bleiben und damit würde das ``del`` auch bei CPython keine sofortige Freigabe des Speichers garantieren. Und nochmal: Ganz allgemein garantiert die Sprachspezifikation weder wann noch ob Speicher von nicht mehr erreichbaren Objekten freigegeben wird. CPython (aktuelle Implementierung(en)) dagegen *garantiert* sogar das die Knoten-Objekte von so einer doppelt verketteten Liste *nie* freigegeben werden wenn sie eine eigene `__del__()`-Methode implementieren!
Natürlich wird man bei einer `pop()`-Implementierung einer doppelt verketteten Liste den Zyklus in der Referenzierung aufbrechen *müssen*. Es geht um so etwas:
Code: Alles auswählen
doubly_linked_list = LinkedList([23, 42, 4711])
del doubly_linked_list
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
Ja, da hast Du vollkomen recht, es ist nicht exakt dasselbe Problem. Ich habe noch einmal darüber nachgedacht und finde diese Zeile besonders interessant:cofi hat geschrieben:Nochmal: Das sind zwei verschiedene Probleme. Das gezeigte ist genau das was du nicht verstehen willst: Objekte werden nicht geloescht obwohl sie nicht erreichbar und damit einen Reference Count von 0 haben.
Deine Neukonstruktion ist das Ueberschreiben von Namen, damit sind die letzten 9 nicht mehr erreichbar und werde _moeglicherweise_ geloescht, aber das 10. nicht.
Diese 2 Situationen sind absolut nicht dasselbe Problem.
Code: Alles auswählen
execfile('foo.py', {})
Richtig formuliert ist diese Zeile höchstwahrscheinlich die Lösung aller Memory Leak Probleme, die mit Laden und Ausführen von Scripten in nicht limitierter Anzahl auftreten. Ich habe es noch nicht ausprobiert, aber ich denke, dass es so klappen könnte:
Code: Alles auswählen
a = {}
execfile('foo.py',a)
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
jens hat geschrieben:Es steht noch nach wie vor aus, beweise dafür zu zeigen, das es überhaupt ein Problem gibt
Alfons Mittelmeyer hat geschrieben:die Lösung aller Memory Leak Probleme, die mit Laden und Ausführen von Scripten in nicht limitierter Anzahl auftreten. Ich habe es noch nicht ausprobiert
jens hat geschrieben:Mal abgesehen davon ob nun ein memoryleak existiert oder nicht:
Wie lange arbeitet man wohl mit einem GUI Designer am Stück?!? Wie viel Elemente erstellt man und verwirft sie wieder?
- cofi
- Python-Forum Veteran
- Beiträge: 4432
- Registriert: Sonntag 30. März 2008, 04:16
- Wohnort: RGFybXN0YWR0
Damit hast du nun den Namen `a` der die Referenz auf den Namensraum haelt. Der war davor nicht da, der Referenzzaehler des Namensraumes (und transitiv dann auch aller Objekte, die nur dort existiert haben) war davor auf 0 und _trotzdem_ wurde er nicht entfernt.
Solltest du jetzt also meinen, `del a` hilft gegen das Problem: Tut es nicht.
Solltest du jetzt also meinen, `del a` hilft gegen das Problem: Tut es nicht.
Michael Markert ❖ PEP 8 Übersetzung ❖ Tutorial Übersetzung (3.x) ⇒ Online-Version (Python 3.3) ❖ Deutscher Python-Insider ❖ Projekte
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
Jetzt brauche ich ja kein del mehr, denn durch a = {} ist dieser Namensraum bekannt und kann von der Speicherverwaltung automatisch abgeräumt werden.cofi hat geschrieben:Damit hast du nun den Namen `a` der die Referenz auf den Namensraum haelt. Der war davor nicht da, der Referenzzaehler des Namensraumes (und transitiv dann auch aller Objekte, die nur dort existiert haben) war davor auf 0 und _trotzdem_ wurde er nicht entfernt.
Solltest du jetzt also meinen, `del a` hilft gegen das Problem: Tut es nicht.
Und ob man die letzte Anwendung nach Ausführung noch im Speicher läßt. Da könnte man zwar del benützen. Aber darauf kommt es wohl wirklich nicht an.
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
Das mit eval ganz weg geht nicht, denn execfile gab es in python2, in python3 aber nicht mehr. And dafür muss man reinladen, kompilieren und dann entweder exec oder eval nehmen, was aber bei Kompilaten ziemlich dasselbe ist.jens hat geschrieben:Er wird einsichtig. Dabei wurde das von Anfang an nahegelegt....
Nun noch von eval ganz weg und import nehmen...
Und einsichtig bin ich auch nicht, ich habe nur die beste Lösung gefunden. Die Kritik, dass del nichts bringt, war nicht richtig. Und irgendeinen Tip für eine Lösung konnte mir niemand geben.
Import dagegen wäre Unsinn, denn import ist für Module. Und Module sollen Funktionen und dergleichen haben, auf die man zugreifen kann. Hier geht es aber um Scripts mit rein gar nichts auf das man zugreifen kann.
Zuletzt geändert von Alfons Mittelmeyer am Samstag 15. August 2015, 19:19, insgesamt 2-mal geändert.
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
Ja toll mit import. Mit einem Modul, das dann so aussieht:
Code: Alles auswählen
Außerdem hat man das Problem der Memory Leaks mit so einem Modul nicht gelöst.
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Ich glaube du zäumst das Pferd von hinten auf...
Wie generierst du den Code? Aus welchen Informationen?
Kannst du nicht auch gleich die lebenden Objekte erzeugen, statt code als strings?
Wie willst du einmal generierten Code, der in einer .py Datei gespeichert ist, wieder ans leben bekommen und dann wieder Objekte haben, deren Eigenschaften man wieder ändern und alles wieder speichern kann?
eval() brauchst du hier IMHO nicht.
Hast du dir inzwischen mal existierende GUI-Designer angesehen?
Wie generierst du den Code? Aus welchen Informationen?
Kannst du nicht auch gleich die lebenden Objekte erzeugen, statt code als strings?
Wie willst du einmal generierten Code, der in einer .py Datei gespeichert ist, wieder ans leben bekommen und dann wieder Objekte haben, deren Eigenschaften man wieder ändern und alles wieder speichern kann?
eval() brauchst du hier IMHO nicht.
Hast du dir inzwischen mal existierende GUI-Designer angesehen?
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
Hab es mal ein bisschen geändert und bekomme das raus:DasIch hat geschrieben:eval() und exec leaken sehr leicht Referenzen.Dadurch lassen sich sehr leicht Memory Leaks produzierenCode: Alles auswählen
>>> eval(compile('foo = 1', '<string>', 'exec')) >>> foo 1
Wo wir übrigens bei Memory Leaks sind, folgendes als "foo.py" speichern:Code: Alles auswählen
class Foo(object): def __del__(self): print 'Collected' f = Foo()
So schnell haben wir ein Memory Leak mit exec was wir ohne gar nicht hätten.Code: Alles auswählen
λ python foo.py Collected λ python Python 2.7.10 (default, Jun 3 2015, 19:28:03) [GCC 4.2.1 Compatible Apple LLVM 6.1.0 (clang-602.0.49)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import gc >>> for _ in range(10): ... execfile('foo.py', {}) ... print gc.collect(), len(gc.garbage) ... 9 1 9 2 9 3 9 4 9 5 9 6 9 7 9 8 9 9 9 10
Code: Alles auswählen
>>> import collect
>>> collect.start()
Collected
8 0
Collected
8 0
Collected
8 0
Collected
8 0
Collected
8 0
Collected
8 0
Collected
8 0
Collected
8 0
Collected
8 0
Collected
8 0
Ach so mein Code war so:
Code: Alles auswählen
import gc
def start():
a = {}
for _ in range(10):
execfile('foo.py',a)
a.clear()
a = {}
print gc.collect(), len(gc.garbage)
Du siehst nicht ein das ``del`` keine Lösung für das eingebildete Problem ist, welches keiner Lösung bedarf. Immer noch nicht. Ich denke man sollte jedes Thema in dem Du wieder mit diesem Unsinn anfängst schliessen. Das bringt nichts, ausser Verwirrung bei Leuten die Dein absolutes nicht-verstehen(-wollen) für bare Münze nehmen und Deine Lalaland-Ansichten von ``del`` und Dokumentationen am Ende noch glauben.Alfons Mittelmeyer hat geschrieben:Und einsichtig bin ich auch nicht, ich habe nur die beste Lösung gefunden.