Müssen geöffnete Dateien wieder geschlossen werden?

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
kaineanung
User
Beiträge: 145
Registriert: Sonntag 5. April 2015, 20:57

Hallo Leute, ich habe da mal wieder eine Frage.

Ich habe gerade ein leeres temporäres File erstellt mit

Code: Alles auswählen

tmpfile = open("./temp","w")
Dabei ist mir aufgefallen daß ich an mehreren anderen Stellen die Datei nicht wieder schliesse.

z.B. beim Öffnen meiner Config-/Parameter-Datei:

Code: Alles auswählen

tree = ET.parse(open("./program.xml",'r+'))
So, jetzt stellt sich mir natürlich die Frage ob ich das falsch gemacht habe und die geöffnete Datei permanent geöffnet geblieben ist (ich hoffe doch nur bis zum Programmende zumindest)?
Wie macht ihr das in so einem Falle bzw. was ist die richtige Vorgehensweise?
BlackJack

@kaineanung: Ja, man sollte Dateien auch wieder schliessen. Sie werden zwar spätestens am Programmende geschlossen, aber Dateihandles sind in der Regel begrenzte Systemressourcen. Ausserdem müssen bei Dateien die nicht geschlossen wurden, nicht zwangsläufig alle Daten in die Datei geschrieben worden sein. Das führt auch gerne mal zu Problemen, zum Beispiel wenn man temporäre Dateien zur Kommunikation mit anderen Programmen verwendet.

Statt manuell `close()` aufzurufen sollte man wo es möglich ist die ``with``-Anweisung verwenden. Dann wird die Datei in jedem Fall geschlossen wenn der Programmfluss den ``with``-Block verlässt. Alternativ müsste man mit ``try``/``finally`` arbeiten um das zu gewährleisten.

Edit: 'r+' ist ein eigenartiger Modus für eine XML-Datei, das würde ich nicht machen. Entweder will man die Datei lesen oder man will sie schreiben. Verändern einer bestehenden XML-Datei ist fehleranfällig. Das geht nur wenn die neuen Daten grösser oder mindestens genau gleich gross sind, sonst bekommt man am Ende kein valides XML.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@kaineanung:
Die Sache mit dem Dateien-Schliessen ist eine "Nettigkeit" moderner Betreibssysteme - unter heutigen Windows und POSIX-Systemen wird eine Datei spätenstens mit Prozessende automatisch geschlossen.
Wie Du richtig erkannt hast, öffnet Dein `ET.parse(open("./program.xml",'r+'))` eine Datei implizit im "Hintergrund" aber Du schliesst sie nirgends explizit - kannst Du auch gar nicht, weil Du das filehandle nicht in Python "gebunden" hast. Du vertraust mit Deinem Code quasi darauf, dass sich irgendwer korrekt darum kümmert (Schliesst Pythons Garbage Collector die Datei für mich? Oder das OS? Oder bleibt sie für immer offen?) :shock:

Daher besser explizit als implizit und am besten gleich mit `with` - siehe BlackJacks Antwort.
kaineanung
User
Beiträge: 145
Registriert: Sonntag 5. April 2015, 20:57

Und wie sieht das dann konkret aus in meinem obigen Beispiel?
Ich bekomme ja nicht das Dateihandle zurückgeliefert sondern den Inhalt der Datei.
Daher ist es mit close ja nicht möglich das zu schliessen. Also muss ich mich mit 'with' befassen.

Daher habe ich kurz geggoelt und finde nirgends eine klare Beschreibung mit Beispielen.
Kann mir da jemand das mal kurz erklären oder, noch besser, mir ein Link zukommen lassen wo ich es auch selber anschauen kann was das genau macht und wie und wo man es einsetzen tut?
Danke schon einmal im Voraus!
BlackJack

@kaineanung: Das `open()` liefert schon das Dateiobjekt (was ein bisschen mehr ist als ein Dateihandle), Du benutzt das halt direkt als Argument für einen Aufruf. Wenn Du das vorher an einen Namen binden würdest, könntest über den dann hinterher auch `close()` aufrufen. Und auch für die ``with``-Anweisung musst Du das da aus dem Aufruf heraus holen und mit ``as`` an einen Namen binden.

Der Index in der Python-Dokumentation ist bei so etwas immer sehr praktisch, wenn man einen Namen von einer Funktion, Klasse, einem Modul, oder wie in diesem Fall von einem Schlüsselwort hat. Der Link zum Index ist auf fast jeder Seite der Dokumentation oben rechts. Da dann auf „W“ klicken und in der HTML-Seite nach „with“ suchen. Das fördert zwei Links zutage: The ``with``-Statement und With Statement Context Managers in der Sprachreferenz. Beide Abschnitte enthalten einen Link auf PEP 0343 The with Statement.
Antworten