Ist das explizite Schließen von Dateien wichtig?

149

Wenn Sie in Python entweder eine Datei öffnen, ohne sie aufzurufen close(), oder die Datei schließen, aber nicht verwenden try- finallyoder die withAnweisung " ", ist dies ein Problem? Oder reicht es als Codierungspraxis aus, sich auf die Python-Garbage-Collection zu verlassen, um alle Dateien zu schließen? Zum Beispiel, wenn man dies tut:

for line in open("filename"):
    # ... do stuff ...

... ist dies ein Problem, weil die Datei niemals geschlossen werden kann und eine Ausnahme auftreten kann, die verhindert, dass sie geschlossen wird? Oder wird es am Ende der forErklärung definitiv geschlossen, weil die Datei nicht mehr gültig ist?

user553702
quelle
13
Die Datei verlässt am Ende des Blocks nicht den Gültigkeitsbereich for. Der Referenzzähler wird auf Null gesetzt, wodurch er automatisch geschlossen wird. Es werden jedoch nur Funktionen, Klassen und Module in Python definiert, keine anderen zusammengesetzten Anweisungen.
agf
18
Es ist kein Problem, es sei denn, es ist ein Problem. Auf Betriebssystemebene werden alle vom Skript geöffneten Dateien beim Beenden des Skripts geschlossen, sodass Sie sich keine Gedanken über das Schließen von Dateien in wegwerfbaren Tool-Skripten machen müssen. Prozesse haben jedoch eine Begrenzung für die Anzahl der geöffneten Dateien, die sie verwalten können. Daher müssen langlebige oder komplexe Skripts möglicherweise vorsichtiger sein. In jedem Fall ist es eine gute Angewohnheit, Ihre Dateien zu schließen.
Russell Borogove
3
@agf: Sie haben Recht, dass die Datei nicht außerhalb des Gültigkeitsbereichs liegt, aber sie hängt nicht mit der Unterscheidung zwischen forBlöcken und Funktionen / Klassen / Modulen zusammen. Es ist viel einfacher als das: Objekte haben keine Bereiche, nur Namen. Es gibt keinen Namen, der auf dieses Objekt verweist, daher gibt es hier nichts, was im Geltungsbereich bleiben oder den Geltungsbereich verlassen könnte.
Max
@max Mein Kommentar korrigiert seine Annahme, dass der forSchleife ein Bereich zugeordnet ist, und erwähnt, dass die Datei aus einem ganz anderen Grund geschlossen wird. Es wird nicht auf die Bereiche in Python eingegangen, da dies hier nicht relevant ist.
Agf
@max gibt es einen impliziten Verweis auf die for-Schleife ... dies ist ein Argument der Semantik
Peter R

Antworten:

126

In Ihrem Beispiel wird nicht garantiert, dass die Datei geschlossen wird, bevor der Interpreter beendet wird. In aktuellen Versionen von CPython wird die Datei am Ende der for-Schleife geschlossen, da CPython die Referenzzählung als primären Speicherbereinigungsmechanismus verwendet. Dies ist jedoch ein Implementierungsdetail und kein Merkmal der Sprache. Andere Implementierungen von Python funktionieren garantiert nicht auf diese Weise. Zum Beispiel verwenden IronPython, PyPy und Jython keine Referenzzählung und schließen daher die Datei am Ende der Schleife nicht.

Es ist eine schlechte Praxis, sich auf die Garbage Collection-Implementierung von CPython zu verlassen, da dadurch Ihr Code weniger portabel wird. Wenn Sie CPython verwenden, treten möglicherweise keine Ressourcenlecks auf. Wenn Sie jedoch jemals zu einer Python-Implementierung wechseln, die keine Referenzzählung verwendet, müssen Sie den gesamten Code durchgehen und sicherstellen, dass alle Ihre Dateien ordnungsgemäß geschlossen sind.

Verwenden Sie für Ihr Beispiel:

with open("filename") as f:
     for line in f:
        # ... do stuff ...
Peter Graham
quelle
8
Wird with open() as fdie Datei nach Abschluss automatisch geschlossen?
Rohan
24
@Rohan ja, das ist die kleine Magie, die die withAnweisung bereitstellt, aber damit diese Magie funktioniert, muss das Objekt die speziellen Methoden haben, __enter__und __exit__in letzterem muss das Objekt die closeund alle anderen Aufräumarbeiten ausführen, die am ausgeführt werden müssen Ende der withErklärung ...
Copperfield
1
Zu Ihrer Information: Diese Antwort erklärt nur "wann es geschlossen werden würde", aber nicht "was ist, wenn es offen bleibt". Für letztere lesen Sie bitte "Was würde passieren, wenn eine Datei geöffnet bleibt?" Teil dieser Antwort ( askubuntu.com/questions/701491/… )
RayLuo
Darüber hinaus kann das Nichtschließen von Dateien zu abgeschnittenen Dateien führen, da der Dateiinhalt nicht gelöscht wurde.
Erwan Legrand
Wenn ich die Datei nicht schließe, bekomme ich dann sicher meinen Speicher zurück, sobald das Programm nicht mehr läuft? Oder muss ich tatsächlich den gesamten Dolmetscher verlassen?
Pro Q
22

Einige Pythons schließen Dateien automatisch, wenn nicht mehr auf sie verwiesen wird, während andere dies nicht tun. Es liegt an den Betriebssystemen, Dateien zu schließen, wenn der Python-Interpreter beendet wird.

Selbst für die Pythons, die Dateien für Sie schließen, ist das Timing nicht garantiert: Es kann sofort oder Sekunden / Minuten / Stunden / Tage später sein.

Obwohl Sie möglicherweise keine Probleme mit dem von Ihnen verwendeten Python haben, ist es definitiv keine gute Praxis, Ihre Dateien offen zu lassen. Tatsächlich erhalten Sie in cpython 3 jetzt Warnungen, dass das System Dateien für Sie schließen musste, wenn Sie dies nicht getan haben.

Moral: Räumen Sie nach sich selbst auf. :) :)

Ethan Furman
quelle
9
Dateien werden geschlossen, wenn in CPython nicht mehr auf sie verwiesen wird. Dies ist jedoch keine Sprachfunktion. Wenn es so wäre, könnten Sie sich ganz glücklich darauf verlassen.
Peter Graham
9

Obwohl es in diesem speziellen Fall ziemlich sicher ist, ein solches Konstrukt zu verwenden, gibt es einige Vorbehalte, um eine solche Praxis zu verallgemeinern:

  • run kann möglicherweise keine Dateideskriptoren mehr haben, obwohl dies unwahrscheinlich ist. Stellen Sie sich vor, Sie suchen nach einem solchen Fehler
  • Auf einigen Systemen, z. B. win32, können Sie diese Datei möglicherweise nicht löschen
  • Wenn Sie etwas anderes als CPython ausführen, wissen Sie nicht, wann die Datei für Sie geschlossen wird
  • Wenn Sie die Datei im Schreib- oder Lese- / Schreibmodus öffnen, wissen Sie nicht, wann Daten gelöscht werden
Dima Tisnek
quelle
3

Die Datei wird mit Müll gesammelt und daher geschlossen. Der GC bestimmt, wann er geschlossen wird, nicht Sie. Dies ist offensichtlich keine empfohlene Vorgehensweise, da Sie möglicherweise das Limit für das Öffnen von Dateihandles erreichen, wenn Sie Dateien nicht schließen, sobald Sie sie nicht mehr verwenden. Was ist, wenn Sie in forIhrer Schleife weitere Dateien öffnen und sie verweilen lassen?

Nam Nguyen
quelle
Wenn Sie jedoch andere Dateien innerhalb dieser for-Schleife öffnen, wird immer noch mehr als eine Datei gleichzeitig geöffnet, unabhängig davon, ob Sie eine davon explizit schließen oder nicht. Wollen Sie damit sagen, dass die Datei nicht unbedingt mit Müll gesammelt wird, sobald die Datei den Gültigkeitsbereich verlässt, sodass sie bei expliziter Ausführung früher geschlossen wird? Was ist, wenn eine Ausnahme auftritt (wenn Sie mit / try-finally verwenden oder nicht)?
user553702
1
In CPython wird die Referenzzählung nach der forAnweisung erfasst - Sie müssen nicht auf den nächsten Speicherbereinigungslauf warten.
agf
3

Hallo, es ist sehr wichtig, den Dateideskriptor zu schließen, wenn Sie den Inhalt im selben Python-Skript verwenden möchten. Ich selbst merke heute nach so langem hektischem Debuggen. Der Grund dafür ist, dass Inhalte erst bearbeitet / entfernt / gespeichert werden, nachdem Sie Ihren Dateideskriptor geschlossen haben und Änderungen an der Datei betroffen sind!

Angenommen, Sie schreiben Inhalte in eine neue Datei und verwenden diese Datei (nicht fd) in einem anderen Shell-Befehl, der den Inhalt liest, ohne fd zu schließen. In dieser Situation erhalten Sie nicht wie erwartet Inhalte für den Shell-Befehl, und wenn Sie versuchen, Fehler zu beheben, können Sie den Fehler nicht leicht finden. Sie können auch mehr in meinem Blogeintrag http://magnificentzps.blogspot.in/2014/04/importance-of-closing-file-descriptor.html lesen

Zeel Shah
quelle
1

Während des E / A-Prozesses werden Daten gepuffert. Dies bedeutet, dass sie an einem temporären Speicherort gespeichert werden, bevor sie in die Datei geschrieben werden.

Python leert den Puffer nicht, dh schreibt Daten in die Datei, bis Sie sicher sind, dass Sie mit dem Schreiben fertig sind. Eine Möglichkeit, dies zu tun, besteht darin, die Datei zu schließen.

Wenn Sie in eine Datei schreiben, ohne sie zu schließen, gelangen die Daten nicht in die Zieldatei.

Sanket Nagrale
quelle