Nach dem schließen der Datei löschen

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
wuif
User
Beiträge: 1
Registriert: Montag 16. Januar 2006, 16:05
Wohnort: Poels/Graz/Kapfenberg

Hallo Leute!

Ich hätte eine Frage, hoffe ihr könnt mir weiterhelfen.

Ich schreibe mit Python meine Testdaten in ein XML File. Während ich diese Testdaten schreibe, kann ich in einem GUI den Testvorgang abbrechen und dadurch wird mein XML-File ungültig. Deshalb möchte ich es nach dem Abbruch zuerst schließen und danach gleich löschen.
Das Funktioniert aber leider nicht weil ich eine Os.Error bekomme. Meine Frage wäre, wie ich das löse könnte? Ich muss unbedingt zu diesem Zeitpunkt die Datei löschen.

Danke für eure Hilfe

Mit freundlichen Grüßen
henning
User
Beiträge: 274
Registriert: Dienstag 26. Juli 2005, 18:37

Wobei genau kriegst du den den OSError?
Beim schließen?
Ist sie dann vielleicht schon geschlossen?

Oder kriegst du ihn beim löschen? Dann könnte es daran liegen, dass die Datei noch gar nicht angelegt wurde, und/oder vielleicht noch geöffnet ist.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Also ich würde eine Funktion als Handler bei atexit anlegen, die die Datei löscht. Aber dabei darf die Datei natürlich nicht geöffnet oder gar in Bearbeitung sein!

Ansonsten frage ich mich das gleiche wie henning ;)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
Michael Schneider
User
Beiträge: 569
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Brandenburg

Während ich auch schon auf die große Antwort gepannt bin, hier ein weiterer Vorschlag: wie wäre es mit einer Wrapper-Klasse? Ich habe mal was zusammengebastelt...

Code: Alles auswählen

import os

class FILE:
	def __init__(self, *args, **kw):
		self.file = apply(open, args, kw)
		self.filename = self.file.name
		
	def __del__(self):
		##  Datei loeschen wenn Muellabfuhr kommt
		self.file.close()
		os.remove(self.filename)
		print "Datei %s geloescht!" % self.filename 	##	nur zum Test

## Beispiel		
test = FILE("testfile.tmp", "w")
test.file.write("test")		##	Attribut file als Dateiobjekt verwenden
del test
Damit muss man zwar das Dateiobjekt über das Attribut "file" ansprechen, dafür braucht man sich aber später um nichts mehr zu kümmern.
Wenn jemand die Adresse vom File-Objekt nennen könnte, dann kann man das direkt ableiten.
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Also ich würde das mit Wrapperklassen sein lassen, das sieht vergleichsweise unsauber aus. Warum? Weil man auf das File per Wrapperklassen-Attribut zugreift und __del__ ist sowieso ein zweischneidiges Schwert.
Michael Schneider hat geschrieben:Wenn jemand die Adresse vom File-Objekt nennen könnte, dann kann man das direkt ableiten.
Die "Adresse" oder eher das Objekt von File-Objekten ist das Objekt.. file. Also etwa class DeletingClass(file).

Aber wenn Michael schon einen Code einwirft, will ich doch nicht schlechter sein:

Code: Alles auswählen

import atexit, os

filename = 'stuff.xml'

def removefile():
    os.remove(filename)

atexit.register(removefile)

f = file(filename, 'w')
f.write('<xmlstuff />')
f.close()
Eine ganz andere Idee wäre es, die XML-Daten in ein StringIO-Objekt zu schreiben und wenn der Testvorgang erfolgreich abgeschlossen wird dann in ein file-Objekt kopieren. Wenn der vorgang nicht erfolgreich ist, kann man das StringIO-Objekt auch einfach eintonnen und muss sich nicht um das Löschen kümmern.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Joghurt
User
Beiträge: 877
Registriert: Dienstag 15. Februar 2005, 15:07

Wie? Kann Windows das nicht?

Unter Unix/Linux kannst du eine Datei löschen, Programme, die sie geöffnet haben, können weiterhin damit arbeiten, bis sie sie schließen.
Benutzeravatar
Michael Schneider
User
Beiträge: 569
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Brandenburg

Leonidas hat geschrieben:Also ich würde das mit Wrapperklassen sein lassen, das sieht vergleichsweise unsauber aus. Warum? Weil man auf das File per Wrapperklassen-Attribut zugreift und __del__ ist sowieso ein zweischneidiges Schwert.
Das war nur ein spontaner Gedanke. Die Wrapper-Klasse sieht wirklich nicht sehr sauber aus, das gebe ich zu. Ich zögerte nur, weil mir über type(file) der Typ "Type" angegeben wurde. Was genau meinst Du mit "zweischneidiges Schwert"?

Ich habe mich mal an dem Code für die abgeleitete Klasse versucht:

Code: Alles auswählen

import os
class FILE(file):
    def __init__(self, *args, **kw):
        apply(file.__init__, (self,)+ args, kw)
        
    def __del__(self):
        self.close()
        self.os.remove(self.name)
Dabei merkt man von außen auch nur, dass es kein original-Fileobjekt ist, weil es die Methoden __init__ und __del__ gibt.
Leonidas hat geschrieben: Aber wenn Michael schon einen Code einwirft, will ich doch nicht schlechter sein:

Code: Alles auswählen

import atexit, os
...
atexit.register(removefile)
...
Interessant, das Modul atexit kannte ich noch gar nicht. Aber wenn ich wuif richtig verstanden habe, möchte er die Datei gleich löschen, wenn sie ungültig wird (ausgelöst über die GUI) und nicht unbedingt erst am Programmende. Wenn die Chance sehr hoch ist, dass die Datei für den Müll erzeugt wird, dann hätte ich auch StringIO vorgeschlagen, das verschwindet ebenfalls mit der Müllabfuhr.

Allen guten Vorschlägen (außer StringIO) zum Trotz wäre es in diesem Fall das sinnvollste, den eigentlichen Grund für den IO-Fehler zu finden und die Lösung in den GUI-Handler einzubauen. In diesem Sinne noch einmal die Frage an wuif: bitte prüf die Zeile des Trace-Backs nach dem eigentlichen Grund für den IO-Fehler!
Diese Nachricht zersört sich in 5 Sekunden selbst ...
BlackJack

Michael Schneider hat geschrieben:Das war nur ein spontaner Gedanke. Die Wrapper-Klasse sieht wirklich nicht sehr sauber aus, das gebe ich zu. Ich zögerte nur, weil mir über type(file) der Typ "Type" angegeben wurde. Was genau meinst Du mit "zweischneidiges Schwert"?
Es wird von Python nicht garantiert wann und in welcher Reihenfolge die `__del__()` Methoden aufgerufen werden. Also zum Beispiel muss das nicht zwingend der Fall sein, nachdem das Dateiobjekt von Python aus nicht mehr erreichbar ist.

Eine weitere Falle: Wenn die IOException eine Referenz auf das Dateiobjekt enthält, dann besteht die solange bis eine weitere Ausnahme ausgelöst wird und die alte ersetzt. Die jeweils letzte Ausnahme merkt sich Python nämlich.

Und wenn man `__del__()` verwendet, dann kann CPython keine zirkulären Referenzen zwischen diesen Objekten mehr erkennen, das heisst, die muss man selbst "aufbrechen" wenn man sicher gehen will, dass der Speicher wieder freigegeben wird und `__del__()` auf den beteiligten Objekten aufgerufen wird.

Das einfachste wäre es wohl die Datei vor dem löschen einfach zu schliessen. Falls das denn der IO-Fehler sein sollte.
Antworten