Ich bekomme es ohne eval nicht hin

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.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

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?

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

@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:

Code: Alles auswählen

doubly_linked_list = LinkedList([23, 42, 4711])
del doubly_linked_list
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!
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

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.
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:

Code: Alles auswählen

execfile('foo.py', {})
Es ist eine sehr gute Idee, einen neuen unabhängigen Namensraum zu verwenden. So brauche ich etwa beim GUI Designer keinerlei Rücksicht nehmen, welche Funktionen die Anwendung haben könnte, sofern der GUI Designer zu einer bereits existierenden Anwendung dazu exportiert wird. Und kann meine Implementation in beliebiger Form gestalten. Diese Zeile enthält nur einen klitzeklein aussehenden Fehler, der aber verhindert, dass die Speicherverwaltung von Python greifen kann.

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)
Benutzeravatar
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 :P
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?

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
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.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

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.
Jetzt brauche ich ja kein del mehr, denn durch a = {} ist dieser Namensraum bekannt und kann von der Speicherverwaltung automatisch abgeräumt werden.

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.
Benutzeravatar
HarteWare
User
Beiträge: 69
Registriert: Samstag 23. Februar 2013, 21:16
Wohnort: localhost

Don't feed the Troll
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Er wird einsichtig. Dabei wurde das von Anfang an nahegelegt....

Nun noch von eval ganz weg und import nehmen...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

jens hat geschrieben:Er wird einsichtig. Dabei wurde das von Anfang an nahegelegt....

Nun noch von eval ganz weg und import nehmen...
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.

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.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:


GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Ja toll mit import. Mit einem Modul, das dann so aussieht:Ein Leermodul in das man dann reloads macht. Das wird aber nicht empfohlen. Und die Lösung ist ja wahrscheinlich gefunden. Man muss sie nur noch testen.
Außerdem hat man das Problem der Memory Leaks mit so einem Modul nicht gelöst.
Benutzeravatar
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?

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

DasIch hat geschrieben:eval() und exec leaken sehr leicht Referenzen.

Code: Alles auswählen

>>> eval(compile('foo = 1', '<string>', 'exec'))
>>> foo
1
Dadurch lassen sich sehr leicht Memory Leaks produzieren

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()

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
So schnell haben wir ein Memory Leak mit exec was wir ohne gar nicht hätten.
Hab es mal ein bisschen geändert und bekomme das raus:

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
Das mit der 0 hinten schaut gut aus. Aber was ist mit der 8 vorne. Da kenne ich mich nicht so aus. Gut oder schlecht?

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)
Aber ohne clear() ging es nicht. Und was bedeutet das für normale Dictionaries. Reicht da nicht Neuzuweisung, sondern man muss ein clear() machen? Das war allerdings Python 2.7.3. Besser in Python3 sodass es auch ohne clear() geht?
BlackJack

Alfons Mittelmeyer hat geschrieben:Und einsichtig bin ich auch nicht, ich habe nur die beste Lösung gefunden.
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.
Gesperrt