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

@Alfons Mittelmeyer: *Wir* *wissen* es ja, *Du* stellst aufgrund falscher Annahmen unwahre Behauptungen auf. Und bist nicht willens diese *Deine* Annahmen zu überprüfen. Hör auf diesen Unsinn ständig zu wiederholen ohne Ahnung davon zu haben, was Du selber zugibst, und ohne bereit zu sein auch Beweise für Deine obskuren Behauptungen zu liefern, statt fadenscheiniger Ausflüchte.

Noch weniger Zeit kostet es kein ``del`` zu verwenden wofür es nicht gedacht ist und keine `del_all()`-Funktion zu schreiben die es nicht geben kann/wird.

Diese Themen würden wohl auch weniger Zeit kosten wenn man einfach konsequent das Thema dicht macht wenn Du eine Behauptung sinnlos wiederholst ohne Beweise dazu zu liefern. :evil:
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@pillmuncher Danke, da haben wir ja schon was wir brauchen:
globals()

Return a dictionary representing the current global symbol table. This is always the dictionary of the current module (inside a function or method, this is the module where it is defined, not the module from which it is called).
Quelle: https://docs.python.org/2/library/funct ... ml#globals

Also Löschen von bzw. lediglich del von Globals kein Problem.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Genau. Man braucht keine Beweise für das, was offensichtlich ist. Es ist doch wohl klar, dass die Schiffe von der Erde fallen, wenn sie am Horizont verschwinden und nicht mehr wiederkehren. Ist das denn so schwer zu verstehen...? :K
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Alfons Mittelmeyer hat geschrieben:@pillmuncher Danke, da haben wir ja schon was wir brauchen:
[...] https://docs.python.org/2/library/funct ... ml#globals

Also Löschen von bzw. lediglich del von Globals kein Problem.
Nein, du hast es immer noch nicht verstanden. del löscht hier Namen, entfernt aber keine Objekte aus dem Speicher:

Code: Alles auswählen

>>> class C:
...     pass
...
>>> x = C()
>>> y = x
>>> x
<__main__.C object at 0xb6f134cc>
>>> y
<__main__.C object at 0xb6f134cc>
>>> globals()
{'__doc__': None, '__spec__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__builtins__': <module 'builtins' (built-in)>, '__name__': '__main__', '__package__': None, 'y': <__main__.C object at 0xb6f134cc>, 'x': <__main__.C object at 0xb6f134cc>, 'C': <class '__main__.C'>}
>>> del x
>>> globals()
{'__doc__': None, '__spec__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__builtins__': <module 'builtins' (built-in)>, '__name__': '__main__', '__package__': None, 'y': <__main__.C object at 0xb6f134cc>, 'C': <class '__main__.C'>}
>>> y
<__main__.C object at 0xb6f134cc>
In specifications, Murphy's Law supersedes Ohm's.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

pillmuncher hat geschrieben:
Alfons Mittelmeyer hat geschrieben:@pillmuncher Danke, da haben wir ja schon was wir brauchen:
[...] https://docs.python.org/2/library/funct ... ml#globals

Also Löschen von bzw. lediglich del von Globals kein Problem.
Nein, du hast es immer noch nicht verstanden. del löscht hier Namen, entfernt aber keine Objekte aus dem Speicher:

Code: Alles auswählen

>>> class C:
...     pass
...
>>> x = C()
>>> y = x
>>> x
<__main__.C object at 0xb6f134cc>
>>> y
<__main__.C object at 0xb6f134cc>
>>> globals()
{'__doc__': None, '__spec__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__builtins__': <module 'builtins' (built-in)>, '__name__': '__main__', '__package__': None, 'y': <__main__.C object at 0xb6f134cc>, 'x': <__main__.C object at 0xb6f134cc>, 'C': <class '__main__.C'>}
>>> del x
>>> globals()
{'__doc__': None, '__spec__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__builtins__': <module 'builtins' (built-in)>, '__name__': '__main__', '__package__': None, 'y': <__main__.C object at 0xb6f134cc>, 'C': <class '__main__.C'>}
>>> y
<__main__.C object at 0xb6f134cc>
Und wieso nicht? Das Objekt at 0xb6f134cc hat noch die Referenz y, ist also noch eine Referenz darauf vorhanden und ist dadurch noch nicht als Waste deklariert
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Wobei ich denke, dass Alfons Mittelmeyer durchaus verstanden hat, dass Objekte auch nach `del` weiterleben, sofern weitere Bezeichner an das Objekt gebunden wurden. Das Problem ist, dass er nicht begreifen will, dass Python keinerlei Garantien gibt, wann ein Objekt gelöscht wird. Er *glaubt*, durch "sinnvolles" Benutzen von `del` die Kontrolle über den Lebenszyklus von Objekten zu haben. Dies lässt er sich leider nicht ausreden und geht sogar soweit, zu behaupten, dass die Python-Entwickler selbst nicht so genau darüber Bescheid wüssten (was natürlich eine völlig haltlose Unterstellung ist) oder dass sie diesen Part aus irgendwelchen anderen Gründen nicht in die Doku aufgenommen hätten, obwohl er aus seiner Sicht genau so zutrifft. Daher ja auch meine Anspielung auf die langlebige Theorie, dass die Erde eine Scheibe sei...
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Ich weiß nur eins: Programmierer, die fest davon überzeugt sind, einen Weg gefunden zu haben, um den Lebenszyklus von Objekten zu kontrollieren, um quasi eine manuelle Speicherverwaltung in Python zu realisieren, werden sich eines Tages mal ganz böse in den Fuß damit schießen.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

snafu hat geschrieben:Ich weiß nur eins: Programmierer, die fest davon überzeugt sind, einen Weg gefunden zu haben, um den Lebenszyklus von Objekten zu kontrollieren, um quasi eine manuelle Speicherverwaltung in Python zu realisieren, werden sich eines Tages mal ganz böse in den Fuß damit schießen.
Der Lebenszyklus ist genau definiert und steht in der Python Dokumentation. Und dort steht auch, dass der Referenzcounter bei del erniedrigt wird:
Note
del x doesn’t directly call x.__del__() — the former decrements the reference count for x by one, and the latter is only called when x‘s reference count reaches zero.
Quelle: https://docs.python.org/3/reference/datamodel.html

Ist also alles dokumentiert und spezifiziert.

Und hier kann man auch sehen, dass die Dokumentation nicht in das Detail geht:
Deletion is recursively defined very similar to the way assignment is defined. Rather than spelling it out in full details, here are some hints.
Quelle: https://docs.python.org/3/reference/sim ... -statement
Wer sich das nicht selber denken kann, der glaubt anscheinend etwas Falsches.

Und wenn Ihr bisher nur statische Anwendungen programmmiert habt, dann mußtet Ihr Euch um die Lebenszeit von Referenzen noch keine Gedanken machen, denn mit Programmende ist alles weg. Wenn Ihr allerdings während der Laufzeit Widgets löscht und nicht nur tkinter callbacks einsetzt sondern auch eigene - ich hatte message Callbacks implementiert - dann habt Ihr dafür zu sorgen, dass diese Referenzen mit Löschen des zugeordneten Widgets verschwinden, denn sonst habt Ihr einen Crash, wenn der Callback für die Widgets noch da ist, die Widgets allerdings nicht mehr. Del braucht es nicht immer, denn wenn die Referenz in einem dictionary oder einer Liste steht, genügt auch ein pop().
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

snafu hat geschrieben:Ich weiß nur eins: Programmierer, die fest davon überzeugt sind, einen Weg gefunden zu haben, um den Lebenszyklus von Objekten zu kontrollieren, um quasi eine manuelle Speicherverwaltung in Python zu realisieren, werden sich eines Tages mal ganz böse in den Fuß damit schießen.
Wer ohne Bedenken den Speicher vollmüllt und glaubt, Python wird das schon automatisch richten, der wird sich eines Tages mal ganz böse ins Knie schießen. So etwas kann bei manchen Anwendungen gar Menschenleben kosten.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@Alfons Mittelmeyer: Achso, ich beginne zu ahnen, wo du falsch liegst.

Der GC darf Objekte aufräumen, deren Referenzzähler == 0 ist (in CPython, andere Pythons können das anders handhaben). Der GC ist aber nicht verpflichtet, dieses Aufräumen zu irgendeinem bestimmten Zeitpunkt - oder überhaupt - auszuführen. Er kann, aber er muss nicht. Und manchmal kann er selbst dann nicht, wenn der Referenzzähler == 0 ist, nämlich wenn ihm eine __del__() Methode ein Bein stellt. An der Stelle, die du zitierst, wird darauf hingewiesen, dass __del__() aufgerufen wird, wenn der Referenzzähler == 0 ist. __del__() steht aber in keiner Beziehung zum GC und ein Aufruf von __del__() beeinflusst nicht den GC, außer indem sie ihn, sofern sie schlecht programmiert wurde, daran hindert, ein Objekt freizugeben. __del__() führt in keiner Weise proaktiv dazu, dass der GC etwas tut. __del__() ist auch kein Destruktor.

Python gibt einem bestimmte Garantien, und bestimmte andere Garantien gibt es einem nicht. Garantiert ist, dass ein Objekt nicht gelöscht wird, bevor sein Referenzzähler == 0 ist. Garantiert ist nicht, dass es sofort oder überhaupt gelöscht wird, nachdem sein Referenzzähler == 0 ist.
In specifications, Murphy's Law supersedes Ohm's.
BlackJack

@Alfons Mittelmeyer: In der Dokumentation steht auch:
CPython implementation detail: CPython currently uses a reference-counting scheme with (optional) delayed detection of cyclically linked garbage, which collects most objects as soon as they become unreachable, but is not guaranteed to collect garbage containing circular references. […] Other implementations act differently and CPython may change. Do not depend on immediate finalization of objects when they become unreachable […].
Man kann also nicht einfach so sagen ``del`` verringert Referenzzähler und auch nicht das der Speicher eines nicht mehr von Code erreichbaren Objekts sofort freigegeben wird nachdem es nicht mehr erreichbar ist. Denn das garantiert die *Sprache* Python nicht. Referenzzählern gibt es in CPython, aber der Absatz da oben weist eindeutig darauf hin das das nicht in allen Implementierungen so sein muss und sich *das auch bei CPython ändern kann*! Und selbst mit CPython's Referenzzählern ist nicht garantiert das Objekte gelöscht werden sobald sie von Code nicht mehr erreichbar sind, worauf der letzte Satz explizit hinweist. Damit ist ``del`` zur manuellen Speicherverwaltung *ungeeignet*.

Wenn ein Callback für ein Widget noch da ist, das Widget aber nicht mehr, dann gibt es keinen Crash. Schon wieder Unsinn, dessen Beweis Du wohl wieder schuldig bleiben wirst.

Speicherverwaltung *kann* man in Python nur automatisch machen, denn manuell ist nicht vorgesehen. Also schiesst man sich Deiner Ansicht nach mit Python auf jeden Fall eines Tages in den Fuss. Mit Java und anderen Sprachen welche die JVM als Laufzeitumgebung verwenden wahrscheinlich auch. Und mit allen anderen Sprachen die ”nur” eine automatische Speicherbereinigung haben.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Alfons Mittelmeyer hat geschrieben:Wer ohne Bedenken den Speicher vollmüllt und glaubt, Python wird das schon automatisch richten, der wird sich eines Tages mal ganz böse ins Knie schießen. So etwas kann bei manchen Anwendungen gar Menschenleben kosten.
Ganz ehrlich: Ich würde in hochkritischen Bereichen für die Softwarekomponenten, die einfach niemals ausfallen dürfen, wohl eher kein Python verwenden. Dafür gibt es spezialisierte andere Sprachen. Und da muss ich dann eben auf die vielen anderen Vorteile von Python verzichten.

Und warum du denkst, dass man den Speicher vollmüllt, sobald man man den Versuch unterlässt, eine (vermeintlich) manuelle Speicherverwaltung mittels `del` zu implementieren, ist mir auch schleierhaft...

BlackJack hat sich ja nun die Mühe gemacht und die Stelle zitiert, an der die Dokumentation eindeutig sagt, dass die Garantien, die du dir herbei halluzinierst, *nicht* bestehen. Möglicherweise bringt dich das ja endlich zur Einsicht. Aber vermutlich haben die Entwickler aus deiner Sicht an der Stelle mal wieder selbst keine Ahnung, wovon sie schreiben. :mrgreen:
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Hätte nicht gedacht, das hier noch was konstruktives herum kommt. :D

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Vielleicht auch mal ein Verweis auf die Doku für das `gc`-Modul, damit man als Anfänger mal eine Ahnung davon bekommt, wie der Garbage Collector in CPython funktioniert:
gc.collect([generation])

With no arguments, run a full collection. The optional argument generation may be an integer specifying which generation to collect (from 0 to 2). A ValueError is raised if the generation number is invalid. The number of unreachable objects found is returned.
Und zudem:
gc.set_threshold(threshold0[, threshold1[, threshold2]])

Set the garbage collection thresholds (the collection frequency). Setting threshold0 to zero disables collection.

The GC classifies objects into three generations depending on how many collection sweeps they have survived. New objects are placed in the youngest generation (generation 0). If an object survives a collection it is moved into the next older generation. Since generation 2 is the oldest generation, objects in that generation remain there after a collection. In order to decide when to run, the collector keeps track of the number object allocations and deallocations since the last collection. When the number of allocations minus the number of deallocations exceeds threshold0, collection starts. Initially only generation 0 is examined. If generation 0 has been examined more than threshold1 times since generation 1 has been examined, then generation 1 is examined as well. Similarly, threshold2 controls the number of collections of generation 1 before collecting generation 2.
Das sind doch sehr deutlich Anhaltspunkte dafür, dass der GC von CPython ein Objekt nicht unmittelbar abräumen muss, nur weil "scheinbar" keine Referenzen mehr auf das Objekt verweisen. Bei alternativen Python-Implementierungen (Jython, PyPy, ...) kann die automatische Speicherbereinigung dann nochmals ganz anders funktionieren.

Allgemein gesprochen kann die Behandlung von unerreichbaren Objekten wohl eher mit dem Verschieben in den Papierkorb, so wie es von gängigen Desktop-Umgebung für Dateien und ähnlichem gehandhabt wird, verglichen werden. Nur mit dem Unterschied, dass man keine Kontrolle darüber hat, wann dieser Papierkorb geleert wird und prinzipiell auch nicht sicher vorhersehen kann, ob er komplett geleert wurde bzw ob das fragliche Objekt die Leerung irgendwie überlebt hat.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

jens hat geschrieben:Hätte nicht gedacht, das hier noch was konstruktives herum kommt. :D
Das mit keine Garantien bezog sich auf zyklische Referenzen. Aber wer macht schon so etwas wie hier:

Code: Alles auswählen

a = SomeClass()
b = a
c = b
a = c
Bei so etwas gibt es dann keine Garantien dass da überhaupt eine Referenz beseitigt wird

Wer so etwas macht, hat keine Garantien, ob er nun del nimmt oder wie auch immer.
Der Normalfall ist genau definiert und spezifiziert, dieser zyklische Fall allerdings bereitet Probleme.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Es steht noch nach wie vor aus, beweise dafür zu zeigen, das es überhaupt ein Problem gibt :P

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

BlackJack hat geschrieben:Wenn ein Callback für ein Widget noch da ist, das Widget aber nicht mehr, dann gibt es keinen Crash. Schon wieder Unsinn, dessen Beweis Du wohl wieder schuldig bleiben wirst.
Du zeichnest Dich immer mehr durch Sturheit und Aufstellen falscher Behauptungen aus. Dann probier doch einmal das:

Code: Alles auswählen

from tkinter import Button
from tkinter import Tk

root = Tk()


# define a widget
mybutton1 = Button(text="Button 1")
mybutton1.pack()

mybutton2 = Button(text="Button 2")
mybutton2.pack()


# define a function, used as callback
def colorcallback(color):
    mybutton1['bg'] = color
    mybutton2['bg'] = color

# calling the callback
colorcallback('yellow')

# now dynamic, we destroy one button

mybutton2.destroy()

# And what would happen, if we would call the callback now?

colorcallback('yellow')

root.mainloop()
BlackJack

@Alfons Mittelmeyer: Das was Du da zeigst ist keine zyklische Referenz. Da ist am Ende einfach nur das selbe Objekt an drei verschiedene Namen gebunden und diese drei Bindungen sind völlig unabhängig voneinander. Zudem ist die letzte Zeile überflüssig darum würde man die nicht schreiben, denn `a` ist ja bereits an das selbe Objekt gebunden wie `c`, die letzte Zuweisung hat also keinen sinnvollen oder die Bindungen betreffenden sichtbaren Effekt. Das zeigt mal wieder Dein Unverständnis von dem was in der Dokumentation beschrieben ist und den Zusammenhängen bei der automatischen Speicherverwaltung.

Der Normalfall ist spezifiziert und zwar so dass von der Sprachspezifikation keinerlei Garantien gegeben werden wann und ob der Speicher von Objekten freigegeben wird. Wenn Du die Dokumentation anders verstehst, dann hast Du sie genau so wenig verstanden wie zyklische Referenzen zwischen Objekten. Die übrigens in der Praxis durchaus vorkommen, das ist bei weitem nichts exotisches, wie Du das anscheinend suggerieren möchtest wenn Du schreibst „Wer so etwas schreibt…” als wenn das nur Leute tun würden die nicht wissen was sie da tun.

Das Beispiel für den Crash ist Unsinn weil es sich bei dem Aufruf nicht um einen Rückruf (Callback) von der Schaltfläche handelt. Den kann es nicht mehr geben, weil es die Schaltfläche ja nicht mehr gibt. Zu dieser richtigen Behauptung stehe ich weiterhin (und meinetwegen auch stur), und würde gernen den Gegenbeweis sehen.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

Alfons Mittelmeyer hat geschrieben:Aber wer macht schon so etwas wie hier
Sowas wie hier macht niemand, weil es völlig sinnfrei ist, das ist aber auch nichtz zyklisches; zyklische Referenzen hast Du aber schon selbst gemacht, wie der Code in Deinem anderen Thread beweist. Übrigens in ObjectiveC sind zyklische Referenzen verboten und müssen vom Programmierer von Hand aufgelöst werden.
Benutzeravatar
sparrow
User
Beiträge: 4193
Registriert: Freitag 17. April 2009, 10:28

Alfons Mittelmeyer hat geschrieben:und habe auch noch kein Buch darüber gelesen.
Das ist offensichtlich und diesen Umstand solltest du ändern.
Gesperrt