Seite 1 von 1

Generator aufräumen auch wenn unbenutzt?

Verfasst: Sonntag 22. Mai 2011, 23:03
von Dauerbaustelle
Tach!

Mit

Code: Alles auswählen

try:
  ... yield ...
finally:
  aufräum()
kann man ja Aufräumarbeiten machen, wenn der Generator zu Ende ist, garbage-collected wird oder eine Exception auftrat.

Wird der aus dem Funktionsaufruf resultierende Generator aber nie angefasst, wird der `finally`-Block natürlich nicht ausgeführt -- kennt jemand eine elegante Möglichkeiten, in diesem Fall Aufräumarbeiten zu erledigen?

Code: Alles auswählen

def somegen():
  try:
    ... yield ...
  finally:
    aufräum()

somegen() # Generator wird nicht "angestoßen"
Dankesehr :-)

Edit: was natürlich geht, ist, das Teil zu wrappen, was aber voraussetzt, dass ich die Aufräumarbeiten außerhalb der Generatorfunktion machen kann. Das würde ich gerne vermeiden.

Re: Generator aufräumen auch wenn unbenutzt?

Verfasst: Sonntag 22. Mai 2011, 23:10
von sma
Ich verstehe das Problem nicht. Dieses Beispiel zeigt "1", "2" und "Cleanup":

Code: Alles auswählen

def g():
    yield 1
    yield 2
    print "Cleanup"

for i in g():
    print i
Wenn man will, kann man auch try/finally benutzen:

Code: Alles auswählen

def g():
    try:
        yield 1
        raise Exception
    finally:
        print "Cleanup"

for i in g():
    print i
Stefan

Re: Generator aufräumen auch wenn unbenutzt?

Verfasst: Sonntag 22. Mai 2011, 23:17
von Dauerbaustelle
sma hat geschrieben:Ich verstehe das Problem nicht. Dieses Beispiel zeigt "1", "2" und "Cleanup":

Code: Alles auswählen

def g():
    yield 1
    yield 2
    print "Cleanup"

for i in g():
    print i

Code: Alles auswählen

def g():
    yield 1
    yield 2
    print "Cleanup"

g()
zeigt aber kein "Cleanup". Ich suche eine Möglichkeit, auch dann Aufräumarbeiten durchzuführen, wenn der Generator niemals "betreten" wird.

Re: Generator aufräumen auch wenn unbenutzt?

Verfasst: Sonntag 22. Mai 2011, 23:26
von sma
Warum willst du etwas aufräumen, wenn du noch gar nichts getan hast? In deinem Beispiel wird doch überhaupt kein Code von g() durchlaufen. Dazu musst du erst einmal next() auf dem von g() zurückgelieferten Generator aufrufen. Und dann funktioniert auch wieder try/finally wie gewohnt.

Stefan

Re: Generator aufräumen auch wenn unbenutzt?

Verfasst: Sonntag 22. Mai 2011, 23:35
von Dauerbaustelle
sma hat geschrieben:Warum willst du etwas aufräumen, wenn du noch gar nichts getan hast?
Extra für dich hol' ich ein wenig weiter aus. :-P

Der Generator iteriert über das Resultat einer Map/Reduce-Operation auf MongoDB, das in einer temporären Collection (das MongoDB-Äquivalent zu Tabellen, falls du dich damit nicht auskennst) gespeichert wird. Jetzt möchte ich ein Argument `drop_collection` anbieten, das, wenn angegeben, die temporäre Collection löscht, wenn der Iterator aufgebraucht ist (oder ein Fehler auftrat etc). Und eben auch, wenn der User das Resultat gar nicht benutzt. (Klar ist das ein Corner Case, ich hätte es aber trotzdem gerne.)

Der Code in question ist übrigens das hier: https://github.com/django-mongodb-engin ... t__.py#L68

Re: Generator aufräumen auch wenn unbenutzt?

Verfasst: Sonntag 22. Mai 2011, 23:56
von BlackJack
@Dauerbaustelle: Ich kenne mich im Detail mit dem Code nicht aus, aber wo wird denn diese temporäre Collection erzeugt? In der Generatorfunktion? Dann wird sie dort doch nur erzeugt wenn Du das erste Element von dem Generator holst. Davor wird von der Funktion *nichts ausgeführt*!

Re: Generator aufräumen auch wenn unbenutzt?

Verfasst: Montag 23. Mai 2011, 00:02
von Dauerbaustelle
BlackJack hat geschrieben:@Dauerbaustelle: Ich kenne mich im Detail mit dem Code nicht aus, aber wo wird denn diese temporäre Collection erzeugt? In der Generatorfunktion? Dann wird sie dort doch nur erzeugt wenn Du das erste Element von dem Generator holst. Davor wird von der Funktion *nichts ausgeführt*!
Ups. Peinlicher Denkfehler. Klar. Danke!

Re: Generator aufräumen auch wenn unbenutzt?

Verfasst: Montag 23. Mai 2011, 07:26
von Darii
Dauerbaustelle hat geschrieben:Der Generator iteriert über das Resultat einer Map/Reduce-Operation auf MongoDB, das in einer temporären Collection (das MongoDB-Äquivalent zu Tabellen, falls du dich damit nicht auskennst) gespeichert wird. Jetzt möchte ich ein Argument `drop_collection` anbieten, das, wenn angegeben, die temporäre Collection löscht, wenn der Iterator aufgebraucht ist (oder ein Fehler auftrat etc). Und eben auch, wenn der User das Resultat gar nicht benutzt. (Klar ist das ein Corner Case, ich hätte es aber trotzdem gerne.)
Bedenke aber auch den Fall, dass der Interpreter crashed und finally dann nicht ausgeführt wird.

Re: Generator aufräumen auch wenn unbenutzt?

Verfasst: Dienstag 24. Mai 2011, 12:20
von Dauerbaustelle
Darii hat geschrieben:Bedenke aber auch den Fall, dass der Interpreter crashed und finally dann nicht ausgeführt wird.
Jagut, soo wichtig ist das Aufräumen dann auch nicht. ;-)

Re: Generator aufräumen auch wenn unbenutzt?

Verfasst: Dienstag 24. Mai 2011, 17:17
von Xynon1
Wie will man mit *einem* Pythonscript über sichergehen das irgendwas aufgeräumt wird, wenn der Interpreter crashed. Dazu müsste man ja ein zweites Programm haben, welches den Interpreter überwachten, oder? Und wie kann man dann erkennen an welcher Stelle dieser abgekratzt ist?

Re: Generator aufräumen auch wenn unbenutzt?

Verfasst: Dienstag 24. Mai 2011, 18:01
von Darii
Xynon1 hat geschrieben:Wie will man mit *einem* Pythonscript über sichergehen das irgendwas aufgeräumt wird, wenn der Interpreter crashed.
Z.B. indem man vor jedem Durchlauf prüft ob noch alte temporäre Tabellen existieren. Oder man lässt das den Server erledigen, der die temporäre Tabelle löscht, wenn die Verbindung abbricht.